{"_id":"@zxkane/quip-mcp-server","_rev":"5-234561e33a637eb7157dc772d8f7bf7a","name":"@zxkane/quip-mcp-server","dist-tags":{"latest":"1.3.1"},"versions":{"1.0.0":{"name":"@zxkane/quip-mcp-server","version":"1.0.0","keywords":["mcp","mcp-server","model-context-protocol","mcp-server-streamable-http","quip","spreadsheet","csv"],"author":"","license":"MIT","_id":"@zxkane/quip-mcp-server@1.0.0","maintainers":[{"name":"zxkane","email":"me@kane.mx"}],"bin":{"quip-mcp-server":"dist/index.js"},"dist":{"shasum":"7f5edf57210d69e52a8ee061669ad8b78a5abcae","tarball":"https://registry.npmjs.org/@zxkane/quip-mcp-server/-/quip-mcp-server-1.0.0.tgz","fileCount":42,"integrity":"sha512-OjO/xI22PcsaUib34phXdm+T9Cu35g/GFON0zByWqTcfHfMZM4KWwxS9nr6fSuWSPpU0/DCnba10nVqkWEQ61w==","signatures":[{"sig":"MEUCIHP+Ve4R1dTyZdoB2amz82qVC0qlAPGkgMGjP8RUfUkXAiEAxaGlAfGNTcjh+AP5Sn3zuS6JykgjY4X39DlNZu+HYFc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":192645},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"gitHead":"08255676992da2d25f5b1fea9a09c93aae49994b","scripts":{"dev":"ts-node src/index.ts","lint":"eslint . --ext .ts","test":"jest","build":"tsc","start":"node dist/index.js","format":"prettier --write \"src/**/*.ts\"","prepare":"npm run build","lint:fix":"eslint . --ext .ts --fix","test:e2e":"jest --config jest.e2e.config.js","test:watch":"jest --watch","test:coverage":"jest --coverage"},"_npmUser":{"name":"zxkane","email":"me@kane.mx"},"_npmVersion":"10.8.2","description":"MCP server for interacting with Quip spreadsheets","directories":{},"_nodeVersion":"20.19.1","dependencies":{"xlsx":"https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz","axios":"^1.8.4","dotenv":"^16.5.0","cheerio":"^1.0.0","express":"^5.1.0","winston":"^3.17.0","fs-extra":"^11.3.0","commander":"^11.1.0","@types/axios":"^0.9.36","@modelcontextprotocol/sdk":"^1.10.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.6.4","eslint":"^8.48.0","rewire":"^7.0.0","ts-jest":"^29.1.1","ts-node":"^10.9.1","prettier":"^3.0.3","typescript":"^5.2.2","@types/jest":"^29.5.4","@types/node":"^20.17.30","@types/rewire":"^2.5.30","@types/express":"^5.0.1","@types/fs-extra":"^11.0.4","@typescript-eslint/parser":"^6.6.0","@typescript-eslint/eslint-plugin":"^6.6.0"},"_npmOperationalInternal":{"tmp":"tmp/quip-mcp-server_1.0.0_1745938983943_0.3751697642833718","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@zxkane/quip-mcp-server","version":"1.1.0","keywords":["mcp","mcp-server","model-context-protocol","mcp-server-streamable-http","quip","spreadsheet","csv"],"author":"","license":"MIT","_id":"@zxkane/quip-mcp-server@1.1.0","maintainers":[{"name":"zxkane","email":"me@kane.mx"}],"bin":{"quip-mcp-server":"dist/index.js"},"dist":{"shasum":"07d8f9a73e0c5610ee8a334617bf7d4ea740c470","tarball":"https://registry.npmjs.org/@zxkane/quip-mcp-server/-/quip-mcp-server-1.1.0.tgz","fileCount":42,"integrity":"sha512-lYltT7fKlXOx6i3mvPZB+iubex1LwwHn7lQQuirdmt2bz6V2HldFISOTh/7jLKXfFEORmt0U47ZebZWFuMK1hg==","signatures":[{"sig":"MEYCIQCCvXIAjDXD846aizNCgLJAOLdpgDSoB3qyT6J8zpTUigIhAIW5J7UdZW3icedbudtp/4Gt7U0IhNNBBdmUb7r/2BQk","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":237349},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"gitHead":"eda6af3797ae835f1e641ddbc0620d33ff9e44bd","scripts":{"dev":"ts-node src/index.ts","lint":"eslint . --ext .ts","test":"jest","build":"tsc","start":"node dist/index.js","format":"prettier --write \"src/**/*.ts\"","prepare":"npm run build","lint:fix":"eslint . --ext .ts --fix","test:e2e":"jest --config jest.e2e.config.js","test:watch":"jest --watch","test:coverage":"jest --coverage"},"_npmUser":{"name":"zxkane","email":"me@kane.mx"},"_npmVersion":"10.8.2","description":"MCP server for interacting with Quip spreadsheets","directories":{},"_nodeVersion":"20.19.1","dependencies":{"xlsx":"https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz","axios":"^1.8.4","dotenv":"^16.5.0","cheerio":"^1.0.0","express":"^5.1.0","winston":"^3.17.0","fs-extra":"^11.3.0","commander":"^11.1.0","@types/axios":"^0.9.36","@aws-sdk/client-s3":"^3.799.0","@modelcontextprotocol/sdk":"^1.10.2","@aws-sdk/s3-request-presigner":"^3.799.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.6.4","eslint":"^8.48.0","rewire":"^7.0.0","ts-jest":"^29.1.1","ts-node":"^10.9.1","prettier":"^3.0.3","typescript":"^5.2.2","@types/jest":"^29.5.4","@types/node":"^20.17.30","@types/rewire":"^2.5.30","@types/express":"^5.0.1","@types/fs-extra":"^11.0.4","@typescript-eslint/parser":"^6.6.0","@typescript-eslint/eslint-plugin":"^6.6.0"},"_npmOperationalInternal":{"tmp":"tmp/quip-mcp-server_1.1.0_1747236440319_0.30673367504642823","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@zxkane/quip-mcp-server","version":"1.2.0","keywords":["mcp","mcp-server","model-context-protocol","mcp-server-streamable-http","quip","spreadsheet","csv"],"author":"","license":"MIT","_id":"@zxkane/quip-mcp-server@1.2.0","maintainers":[{"name":"zxkane","email":"me@kane.mx"}],"bin":{"quip-mcp-server":"dist/index.js"},"dist":{"shasum":"8bc08c64bdc22d75959827dbcc776e2548999eb0","tarball":"https://registry.npmjs.org/@zxkane/quip-mcp-server/-/quip-mcp-server-1.2.0.tgz","fileCount":42,"integrity":"sha512-M3JtTOEVgfZrs+SlPsMR7HdNwNsPQB2YS8O3GmcwjaGttaUkvK8+vNi+hEbtj7j593DTUBMlE9+t3TBytzepXQ==","signatures":[{"sig":"MEUCIFgQuKaWnOd8avupJd68sG8WGFvRnIBhEEn3CqlNRk45AiEAznZHn2L7sl8yeo1+0C8n0GFp2BkS8fYbfylgmUgd5x8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":242983},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"gitHead":"18dd7805a07296bf81d3d8cf9f7ba59ac995eaa9","scripts":{"dev":"ts-node src/index.ts","lint":"eslint . --ext .ts","test":"jest","build":"tsc","start":"node dist/index.js","format":"prettier --write \"src/**/*.ts\"","prepare":"npm run build","lint:fix":"eslint . --ext .ts --fix","test:e2e":"jest --config jest.e2e.config.js","test:watch":"jest --watch","test:coverage":"jest --coverage"},"_npmUser":{"name":"zxkane","email":"me@kane.mx"},"_npmVersion":"10.8.2","description":"MCP server for interacting with Quip spreadsheets","directories":{},"_nodeVersion":"20.19.2","dependencies":{"xlsx":"https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz","axios":"^1.8.4","dotenv":"^16.5.0","cheerio":"^1.0.0","express":"^5.1.0","winston":"^3.17.0","fs-extra":"^11.3.0","commander":"^11.1.0","@types/axios":"^0.9.36","@aws-sdk/client-s3":"^3.799.0","@modelcontextprotocol/sdk":"^1.10.2","@aws-sdk/s3-request-presigner":"^3.799.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.6.4","eslint":"^8.48.0","rewire":"^7.0.0","ts-jest":"^29.1.1","ts-node":"^10.9.1","prettier":"^3.0.3","typescript":"^5.2.2","@types/jest":"^29.5.4","@types/node":"^20.17.30","@types/rewire":"^2.5.30","@types/express":"^5.0.1","@types/fs-extra":"^11.0.4","@typescript-eslint/parser":"^6.6.0","@typescript-eslint/eslint-plugin":"^6.6.0"},"_npmOperationalInternal":{"tmp":"tmp/quip-mcp-server_1.2.0_1749186268090_0.7777571214818635","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@zxkane/quip-mcp-server","version":"1.3.0","keywords":["mcp","mcp-server","model-context-protocol","mcp-server-streamable-http","quip","spreadsheet","csv"],"author":"","license":"MIT","_id":"@zxkane/quip-mcp-server@1.3.0","maintainers":[{"name":"zxkane","email":"me@kane.mx"}],"bin":{"quip-mcp-server":"dist/index.js"},"dist":{"shasum":"cea87d10ee483bd8f5a15695e62ee3002f6996f2","tarball":"https://registry.npmjs.org/@zxkane/quip-mcp-server/-/quip-mcp-server-1.3.0.tgz","fileCount":42,"integrity":"sha512-BnL2lM98FqNZYForsTG0AUnoh1jfziTT/qbTBD8WsXJJDel5uiy1128Mow+XzTvqmdNnM4ouQsJFf/+u/mya6w==","signatures":[{"sig":"MEYCIQDid7SvLcBdjT5Ds50kY06OAzv9r9rT2V1URslDsK8v/AIhAOwvqCGbObB3FPAsWnSNAl0CJSYz0GXNtlDg0ccnpLBA","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":255214},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"gitHead":"754662f269874b1daee4f0c9327605da47110117","scripts":{"dev":"ts-node src/index.ts","lint":"eslint . --ext .ts","test":"jest","build":"tsc","start":"node dist/index.js","format":"prettier --write \"src/**/*.ts\"","prepare":"npm run build","lint:fix":"eslint . --ext .ts --fix","test:e2e":"jest --config jest.e2e.config.js","test:watch":"jest --watch","test:coverage":"jest --coverage"},"_npmUser":{"name":"zxkane","email":"me@kane.mx"},"_npmVersion":"10.8.2","description":"MCP server for interacting with Quip spreadsheets","directories":{},"_nodeVersion":"20.19.4","dependencies":{"xlsx":"https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz","axios":"^1.8.4","dotenv":"^16.5.0","cheerio":"^1.0.0","express":"^5.1.0","winston":"^3.17.0","fs-extra":"^11.3.0","commander":"^11.1.0","@types/axios":"^0.9.36","@aws-sdk/client-s3":"^3.799.0","@modelcontextprotocol/sdk":"^1.16.0","@aws-sdk/s3-request-presigner":"^3.799.0","@aws-sdk/client-secrets-manager":"^3.799.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.6.4","eslint":"^8.48.0","rewire":"^7.0.0","ts-jest":"^29.1.1","ts-node":"^10.9.1","prettier":"^3.0.3","typescript":"^5.2.2","@types/jest":"^29.5.4","@types/node":"^20.17.30","@types/rewire":"^2.5.30","@types/express":"^5.0.1","@types/fs-extra":"^11.0.4","@typescript-eslint/parser":"^6.6.0","@typescript-eslint/eslint-plugin":"^6.6.0"},"_npmOperationalInternal":{"tmp":"tmp/quip-mcp-server_1.3.0_1755188718832_0.8514376001595179","host":"s3://npm-registry-packages-npm-production"}},"1.3.1":{"name":"@zxkane/quip-mcp-server","version":"1.3.1","description":"MCP server for interacting with Quip spreadsheets","main":"dist/index.js","types":"dist/index.d.ts","bin":{"quip-mcp-server":"dist/index.js"},"scripts":{"build":"tsc","start":"node dist/index.js","dev":"ts-node src/index.ts","test":"jest","test:watch":"jest --watch","test:coverage":"jest --coverage","test:e2e":"jest --config jest.e2e.config.js","lint":"eslint . --ext .ts","lint:fix":"eslint . --ext .ts --fix","format":"prettier --write \"src/**/*.ts\"","prepare":"npm run build"},"dependencies":{"@aws-sdk/client-s3":"^3.799.0","@aws-sdk/client-secrets-manager":"^3.799.0","@aws-sdk/s3-request-presigner":"^3.799.0","@modelcontextprotocol/sdk":"^1.17.3","@types/axios":"^0.9.36","axios":"^1.8.4","cheerio":"^1.0.0","commander":"^11.1.0","dotenv":"^16.5.0","express":"^5.1.0","fs-extra":"^11.3.0","winston":"^3.17.0","xlsx":"https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz"},"devDependencies":{"@types/express":"^5.0.1","@types/fs-extra":"^11.0.4","@types/jest":"^29.5.4","@types/node":"^20.17.30","@types/rewire":"^2.5.30","@typescript-eslint/eslint-plugin":"^6.6.0","@typescript-eslint/parser":"^6.6.0","eslint":"^8.48.0","jest":"^29.6.4","prettier":"^3.0.3","rewire":"^7.0.0","ts-jest":"^29.1.1","ts-node":"^10.9.1","typescript":"^5.2.2"},"engines":{"node":">=18.0.0"},"keywords":["mcp","mcp-server","model-context-protocol","mcp-server-streamable-http","quip","spreadsheet","csv"],"author":"","license":"MIT","publishConfig":{"access":"public"},"_id":"@zxkane/quip-mcp-server@1.3.1","gitHead":"994fb6a8704fba40ba221a08d7ac0f8b908f9075","_nodeVersion":"20.19.4","_npmVersion":"10.8.2","dist":{"integrity":"sha512-O63XRXMchFxyM6JT0GaDDxUFnE2V/q3OIRLb1TvGTySL5ehGM7sxxBg5SGMNdjKL8DA33KFkc+ZYe2+hmbao8w==","shasum":"dc7c226455627d75acd1929b23331ca43dfb2b1d","tarball":"https://registry.npmjs.org/@zxkane/quip-mcp-server/-/quip-mcp-server-1.3.1.tgz","fileCount":42,"unpackedSize":255214,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIHiFe7C94nWcVt5vjexp+CGoN0j4RZ18aPfJ2yZyOEM1AiBpEqHogynnyqBdBsuwJYXO02483Tky141pj1k1qOSaNw=="}]},"_npmUser":{"name":"zxkane","email":"me@kane.mx"},"directories":{},"maintainers":[{"name":"zxkane","email":"me@kane.mx"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/quip-mcp-server_1.3.1_1755237423417_0.7298842707918898"},"_hasShrinkwrap":false}},"time":{"created":"2025-04-29T15:03:03.834Z","modified":"2025-08-15T05:57:03.789Z","1.0.0":"2025-04-29T15:03:04.127Z","1.1.0":"2025-05-14T15:27:20.498Z","1.2.0":"2025-06-06T05:04:28.261Z","1.3.0":"2025-08-14T16:25:19.058Z","1.3.1":"2025-08-15T05:57:03.603Z"},"license":"MIT","keywords":["mcp","mcp-server","model-context-protocol","mcp-server-streamable-http","quip","spreadsheet","csv"],"description":"MCP server for interacting with Quip spreadsheets","maintainers":[{"name":"zxkane","email":"me@kane.mx"}],"readme":"[![MseeP.ai Security Assessment Badge](https://mseep.net/pr/zxkane-quip-mcp-server-typescript-badge.png)](https://mseep.ai/app/zxkane-quip-mcp-server-typescript)\n\n# Quip MCP Server (TypeScript)\n\nA Model Context Protocol (MCP) server for interacting with Quip spreadsheets, implemented in TypeScript. This server provides tools to read spreadsheet data from Quip documents and return the content in CSV format.\n\n## 🚀 AWS Pay-as-You-Go Serverless Deployment\n\n**Deploy to AWS with zero infrastructure management and pay only for what you use!**\n\n### ⚡ AWS Agent Core Runtime (Recommended)\n- **🔧 SSE Support**: Built-in Server-Sent Events for real-time streaming\n- **⏱️ Extended Runtime**: Up to 8 hours execution time\n- **📦 Large Payloads**: 100MB payload support\n- **🔐 Built-in Auth**: Integrated OAuth and identity management\n- **💰 Consumption-based**: Pay only for actual runtime usage\n\n```bash\ncd infrastructure/agent-core\n./deploy.sh --agent-name my-quip-mcp --secret-arn arn:aws:secretsmanager:...\n```\n\n### 🌐 AWS Lambda + API Gateway\n- **📈 Auto-scaling**: Handles varying loads automatically\n- **🌍 Global**: Distributed across multiple availability zones\n- **💸 Cost-effective**: Pay per request with generous free tier\n- **🔌 HTTP Interface**: Works with any HTTP MCP client\n\n```bash\ncd infrastructure/api-gateway-lambda\n./deploy.sh --secret-arn arn:aws:secretsmanager:...\n```\n\nBoth options provide enterprise-grade serverless infrastructure with no servers to manage!\n\n## Table of Contents\n\n- [Features](#features)\n- [Installation](#installation)\n  - [Using npm](#using-npm)\n  - [From Source](#from-source)\n  - [Environment Variables](#environment-variables)\n- [Usage](#usage)\n  - [Running the Server](#running-the-server)\n  - [Transport Documentation](#transport-documentation)\n  - [Configure for Claude.app](#configure-for-claudeapp)\n  - [Command Line Arguments](#command-line-arguments)\n  - [Server-Sent Events (SSE) Support](#server-sent-events-sse-support)\n  - [Deploy to AWS Lambda + API Gateway](#deploy-to-aws-lambda--api-gateway)\n- [Available Tools](#available-tools)\n  - [quip_read_spreadsheet](#quip_read_spreadsheet)\n- [Resource URIs](#resource-uris)\n- [How It Works](#how-it-works)\n  - [Error Handling](#error-handling)\n  - [Mock Mode](#mock-mode)\n  - [Structured Logging](#structured-logging)\n  - [Authentication](#authentication)\n  - [Caching](#caching)\n  - [Storage Options](#storage-options)\n    - [Local Storage](#local-storage)\n    - [S3 Storage](#s3-storage)\n- [Health Check Endpoint](#health-check-endpoint)\n- [Cloud Deployment](#cloud-deployment)\n  - [AWS Lambda + API Gateway](#aws-lambda--api-gateway)\n  - [AWS Agent Core Runtime](#aws-agent-core-runtime)\n- [Development](#development)\n  - [Project Structure](#project-structure)\n  - [Setting Up a Development Environment](#setting-up-a-development-environment)\n  - [Scripts](#scripts)\n  - [Running Tests](#running-tests)\n  - [Debugging](#debugging)\n  - [Adding New Tools](#adding-new-tools)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Features\n\n- Retrieve spreadsheet content from Quip documents\n- Support for selecting specific sheets by name\n- Returns data in CSV format with metadata\n- Handles authentication via Quip API token\n- Provides appropriate error messages for non-spreadsheet documents\n- Automatically handles large spreadsheets by truncating content when necessary\n- Stores spreadsheet content locally for efficient access\n- **Multiple storage options** including local filesystem and Amazon S3\n- Provides resource URIs for accessing complete spreadsheet content\n- **Enhanced error handling** with detailed error messages and proper error types\n- **Mock mode** for testing without a real Quip API token\n- **Structured logging** with different log levels (debug, info, warn, error)\n- **API key authentication** for securing the HTTP server\n- **Caching mechanism** for improved performance with frequently accessed resources\n- **Health check endpoint** for monitoring server status\n\n## Installation\n\n### Using npm\n\n```bash\n# Install globally\nnpm install -g @zxkane/quip-mcp-server\n\n# Or install locally in your project\nnpm install @zxkane/quip-mcp-server\n```\n\n### From Source\n\n```bash\n# Clone the repository\ngit clone https://github.com/zxkane/quip-mcp-server-typescript.git\ncd quip-mcp-server-typescript\n\n# Install dependencies\nnpm install\n\n# Build the project\nnpm run build\n```\n\n### Environment Variables\n\nCreate a `.env` file in the root directory with your Quip API token:\n\n```\n# Quip API token (required unless in mock mode)\nQUIP_TOKEN=your_quip_api_token_here\n\n# Quip API base URL (optional, defaults to https://platform.quip.com)\nQUIP_BASE_URL=https://platform.quip.com\n\n# Storage type (optional, defaults to 'local', can be 'local' or 's3')\n# STORAGE_TYPE=local\n\n# Storage path for CSV files (optional, defaults to ~/.quip-mcp-server/storage)\nQUIP_STORAGE_PATH=/path/to/storage\n\n# S3 storage configuration (required when STORAGE_TYPE=s3)\n# S3_BUCKET=your-bucket-name\n# S3_REGION=us-east-1\n# S3_PREFIX=quip-data/\n# S3_URL_EXPIRATION=3600\n\n# MCP server port (optional, defaults to 3000)\nMCP_PORT=3000\n\n# Debug mode (optional, set to true to enable debug logging)\n# QUIP_DEBUG=true\n\n# Mock mode (optional, set to true to use mock data without a real Quip token)\n# QUIP_MOCK=true\n\n# JSON logging (optional, set to true to output logs as JSON)\n# JSON_LOGS=true\n\n# Authentication (optional, set to true to enable API key authentication)\n# MCP_AUTH_ENABLED=true\n\n# API key for authentication (optional, auto-generated if not provided)\n# MCP_API_KEY=your_api_key_here\n\n# API key header name (optional, defaults to X-API-Key)\n# MCP_API_KEY_HEADER=X-API-Key\n```\n\n## Usage\n\n### Running the Server\n\n```bash\n# Using npm with stdio transport (default)\nnpm start\n\n# With command-line arguments\nnpm start -- --storage-path /path/to/storage --file-protocol --debug\n\n# Using HTTP transport (set PORT and HOST environment variables)\nPORT=3000 HOST=localhost npm start\n\n# Using node directly\nnode dist/index.js --storage-path /path/to/storage\n```\n\nThe server supports two transport protocols:\n\n1. **stdio transport** (default): Used when running as a subprocess for tools like Claude.app\n2. **HTTP transport**: Used when you want to expose the server over HTTP, which is useful for development or when running as a standalone service\n\nTo use HTTP transport, set the `PORT` environment variable (and optionally `HOST`).\n\nFor detailed information about transport options, configuration, security considerations, and environment-specific examples, see the [Transport Documentation](docs/transport-documentation.md).\n\n### Transport Documentation\n\nThe Quip MCP server supports two transport types:\n\n- **Stdio Transport**: The default transport, used when running the server as a subprocess of another application (e.g., Claude.app).\n- **HTTP Transport**: Used when exposing the server over HTTP, allowing clients to connect over a network.\n\nThe [detailed transport documentation](docs/transport-documentation.md) covers:\n\n- Transport configuration options\n- Security considerations for each transport type\n- Environment-specific examples (local development, Claude.app integration, production deployment, Docker/container usage, CI/CD integration)\n- Troubleshooting common issues\n- Future considerations for transport improvements\n\n### Configure for Claude.app\n\nAdd to your Claude settings:\n\n```json\n\"mcpServers\": {\n  \"quip\": {\n    \"command\": \"node\",\n    \"args\": [\"dist/index.js\", \"--storage-path\", \"/path/to/storage\"],\n    \"env\": {\n      \"QUIP_TOKEN\": \"your_quip_api_token\"\n    }\n  }\n}\n```\n\nIf you want to use the file protocol for resource URIs:\n\n```json\n\"mcpServers\": {\n  \"quip\": {\n    \"command\": \"node\",\n    \"args\": [\"dist/index.js\", \"--storage-path\", \"/path/to/storage\", \"--file-protocol\"],\n    \"env\": {\n      \"QUIP_TOKEN\": \"your_quip_api_token\"\n    }\n  }\n}\n```\n\n### Command Line Arguments\n\nThe server supports the following command line arguments:\n\n- `--storage-type <type>`: Storage type (local or s3, defaults to 'local')\n- `--storage-path <path>`: Path to store CSV files (defaults to QUIP_STORAGE_PATH environment variable or ~/.quip-mcp-server/storage)\n- `--file-protocol`: Use file protocol for resource URIs (instead of quip:// protocol)\n- `--s3-bucket <name>`: S3 bucket name (required for S3 storage)\n- `--s3-region <region>`: S3 region (required for S3 storage)\n- `--s3-prefix <prefix>`: S3 prefix (optional for S3 storage)\n- `--s3-url-expiration <seconds>`: S3 URL expiration in seconds (default: 3600)\n- `--use-presigned-urls`: Generate presigned HTTPS URLs for S3 resources (instead of s3:// URIs)\n- `--debug`: Enable debug logging\n- `--mock`: Use mock mode (no real Quip token required)\n- `--json`: Output logs as JSON\n- `--auth`: Enable authentication\n- `--api-key <key>`: API key for authentication (auto-generated if not provided)\n- `--api-key-header <header>`: API key header name (defaults to X-API-Key)\n- `--port <port>`: HTTP port to listen on (defaults to MCP_PORT environment variable or 3000)\n- `--sse`: Enable SSE (Server-Sent Events) format for responses (defaults to false)\n\n**Example:**\n```bash\nnode dist/index.js --storage-path /path/to/storage --file-protocol --debug\n```\n\n**Example with mock mode:**\n```bash\nnode dist/index.js --mock --storage-path /path/to/storage\n```\n\n**Example with authentication:**\n```bash\nnode dist/index.js --auth --api-key your_api_key_here\n```\n\n**Example with SSE format:**\n```bash\nnode dist/index.js --port 3000 --sse --mock\n```\n\n### Server-Sent Events (SSE) Support\n\nThe server supports Server-Sent Events (SSE) format for HTTP responses through the `--sse` flag. SSE is a web standard that allows servers to push data to clients over a single HTTP connection using the `text/event-stream` content type.\n\n**When to use SSE:**\n- Real-time applications that need streaming responses\n- Integration with systems that expect event-stream format\n- WebSocket alternatives for server-to-client communication\n- Progressive response streaming\n\n**Response Format Differences:**\n\n*With `--sse` flag:*\n```\nContent-Type: text/event-stream\nCache-Control: no-cache\nConnection: keep-alive\n\ndata: {\"jsonrpc\":\"2.0\",\"result\":{\"tools\":[...]},\"id\":1}\n\n```\n\n*Without `--sse` flag (default):*\n```\nContent-Type: application/json\n\n{\"jsonrpc\":\"2.0\",\"result\":{\"tools\":[...]},\"id\":1}\n```\n\n**Testing SSE functionality:**\n```bash\n# Start SSE server\nnode dist/index.js --port 3000 --sse --mock &\n\n# Test with curl\ncurl -H \"Content-Type: application/json\" \\\n     -d '{\"jsonrpc\":\"2.0\",\"method\":\"tools/list\",\"id\":1}' \\\n     http://localhost:3000/mcp\n```\n\nAll MCP protocol methods are supported with SSE format, including error responses. The underlying MCP functionality remains unchanged.\n\n### Deploy to AWS Lambda + API Gateway\n\nThe Quip MCP server can be deployed to AWS Lambda with API Gateway to create a serverless, scalable HTTP endpoint. This setup is ideal for production environments and provides several benefits:\n\n- **Serverless Operation**: No need to manage servers\n- **Auto-scaling**: Handles varying loads automatically\n- **High Availability**: Distributed across multiple availability zones\n- **Cost-effective**: Pay only for what you use\n- **Streamable HTTP Interface**: Works with tools that support HTTP MCP servers\n\nFor detailed deployment instructions, see the [Cloud Deployment](#aws-lambda--api-gateway) section.\n\n## Available Tools\n\n### quip_read_spreadsheet\n\nRetrieves the content of a Quip spreadsheet as CSV.\n\n**Parameters:**\n- `threadId` (required): The Quip document thread ID\n- `sheetName` (optional): Name of the sheet to extract. If not provided, the first sheet will be used.\n\n**Example:**\n```json\n{\n  \"threadId\": \"AbCdEfGhIjKl\",\n  \"sheetName\": \"Sheet1\"\n}\n```\n\n**Response:**\nThe tool returns a JSON object containing:\n- `csv_content`: The spreadsheet content in CSV format (truncated if too large)\n- `metadata`: Additional information about the spreadsheet:\n  - `total_rows`: Total number of rows in the spreadsheet\n  - `total_size`: Total size of the CSV content in bytes\n  - `is_truncated`: Boolean indicating if the content was truncated\n  - `resource_uri`: URI to access the complete spreadsheet content\n\n**Example Response (default protocol):**\n```json\n{\n  \"csv_content\": \"header1,header2\\nvalue1,value2\\n...\",\n  \"metadata\": {\n    \"total_rows\": 1000,\n    \"total_size\": 52840,\n    \"is_truncated\": true,\n    \"resource_uri\": \"quip://AbCdEfGhIjKl?sheet=Sheet1\"\n  }\n}\n```\n\n**Example Response (with --file-protocol):**\n```json\n{\n  \"csv_content\": \"header1,header2\\nvalue1,value2\\n...\",\n  \"metadata\": {\n    \"total_rows\": 1000,\n    \"total_size\": 52840,\n    \"is_truncated\": true,\n    \"resource_uri\": \"file:///path/to/storage/AbCdEfGhIjKl-Sheet1.csv\"\n  }\n}\n```\n\n**Example Response (with S3 storage):**\n```json\n{\n  \"csv_content\": \"header1,header2\\nvalue1,value2\\n...\",\n  \"metadata\": {\n    \"total_rows\": 1000,\n    \"total_size\": 52840,\n    \"is_truncated\": true,\n    \"resource_uri\": \"s3://my-bucket/quip-data/AbCdEfGhIjKl-Sheet1.csv\"\n  }\n}\n```\n\n**Example Response (with S3 storage and --use-presigned-urls):**\n```json\n{\n  \"csv_content\": \"header1,header2\\nvalue1,value2\\n...\",\n  \"metadata\": {\n    \"total_rows\": 1000,\n    \"total_size\": 52840,\n    \"is_truncated\": true,\n    \"resource_uri\": \"https://my-bucket.s3.us-east-1.amazonaws.com/quip-data/AbCdEfGhIjKl-Sheet1.csv?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...\"\n  }\n}\n```\n\n**Error Handling:**\n- If the thread is not a spreadsheet, an error will be returned.\n- If the specified sheet is not found, an error will be returned.\n\n### Resource URIs\n\nThe server provides resource URIs for accessing complete spreadsheet content. These URIs can be used with the MCP resource access mechanism.\n\nThe server supports multiple URI formats depending on the configuration:\n\n#### Default Protocol (quip://)\n\n**URI Format:**\n```\nquip://{threadId}?sheet={sheetName}\n```\n\n**Example:**\n```\nquip://AbCdEfGhIjKl?sheet=Sheet1\n```\n\n#### File Protocol (with --file-protocol option)\n\n**URI Format:**\n```\nfile://{storage_path}/{threadId}-{sheetName}.csv\n```\n\n**Example:**\n```\nfile:///home/user/.quip-mcp-server/storage/AbCdEfGhIjKl-Sheet1.csv\n```\n\n#### S3 Protocol (when using S3 storage)\n\n**URI Format:**\n```\ns3://{bucket}/{prefix}/{threadId}-{sheetName}.csv\n```\n\n**Example:**\n```\ns3://my-bucket/quip-data/AbCdEfGhIjKl-Sheet1.csv\n```\n\n#### Presigned S3 URLs (when using S3 storage with USE_PRESIGNED_URLS=true)\n\n**URI Format:**\n```\ns3+https://{bucket}/{prefix}/{threadId}-{sheetName}.csv\n```\n\nWhich resolves to an HTTPS URL:\n```\nhttps://{bucket}.s3.{region}.amazonaws.com/{prefix}/{threadId}-{sheetName}.csv?{authentication_params}\n```\n\n**Example:**\n```\nhttps://my-bucket.s3.us-east-1.amazonaws.com/quip-data/AbCdEfGhIjKl-Sheet1.csv?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...\n```\n\nWhen accessed, the resource returns the complete CSV content of the spreadsheet, regardless of size.\n\n## How It Works\n\nThe server uses two methods to extract spreadsheet data:\n\n1. **Primary Method**: Exports the spreadsheet to XLSX format using the Quip API, then converts it to CSV.\n2. **Fallback Method**: If the primary method fails, it parses the HTML content of the document to extract the table data.\n\nFor large spreadsheets, the server:\n1. Saves the complete CSV content to local storage\n2. Returns a truncated version (up to 10KB) with metadata\n3. Provides a resource URI for accessing the complete content\n\n### Error Handling\n\nThe server implements a comprehensive error handling system with specific error types:\n- `QuipMCPError`: Base error class for all server errors\n- `InvalidParamsError`: For invalid request parameters\n- `MethodNotFoundError`: For unknown methods or tools\n- `ParseError`: For JSON parsing errors\n- `AuthenticationError`: For authentication failures\n- `ResourceNotFoundError`: For resource not found errors\n- `QuipApiError`: For Quip API errors\n- `StorageError`: For storage-related errors\n- `TimeoutError`: For request timeout errors\n\nEach error type has a specific error code and can include additional data for debugging. This consistent error handling ensures that clients receive clear and actionable error messages, making it easier to diagnose and fix issues.\n\n### Mock Mode\n\nThe server includes a mock mode that doesn't require a real Quip API token. This is useful for testing and development. In mock mode, the server uses pre-defined sample data instead of making actual API calls to Quip.\n\nTo enable mock mode, use the `--mock` command line argument or set the `QUIP_MOCK` environment variable to `true`.\n\nMock mode provides several sample spreadsheets with different structures and sizes, allowing you to test your application's handling of various data formats without needing access to real Quip documents. This is particularly useful for development environments or CI/CD pipelines where you may not want to use real API credentials.\n\n### Structured Logging\n\nThe server implements structured logging with different log levels:\n- `DEBUG`: Detailed debugging information\n- `INFO`: General information about server operation\n- `WARN`: Warning messages\n- `ERROR`: Error messages\n\nLogs can be output as plain text or JSON format. To enable JSON logging, use the `--json` command line argument or set the `JSON_LOGS` environment variable to `true`.\n\nThe structured logging system provides consistent log formatting and includes contextual information with each log entry, making it easier to filter and analyze logs. When JSON logging is enabled, logs can be easily parsed by log management systems for advanced monitoring and alerting.\n\n### Authentication\n\nThe server supports API key authentication for securing the HTTP server. When enabled, clients must include the API key in the request headers.\n\nTo enable authentication, use the `--auth` command line argument or set the `MCP_AUTH_ENABLED` environment variable to `true`. You can specify the API key using the `--api-key` argument or `MCP_API_KEY` environment variable. If not provided, a random API key will be generated and displayed in the logs.\n\nThe API key header name can be customized using the `--api-key-header` argument or `MCP_API_KEY_HEADER` environment variable. By default, the header name is `X-API-Key`.\n\nAuthentication is only applied to the HTTP transport mode and does not affect stdio transport, which is typically used in more controlled environments.\n\n### Caching\n\nThe server implements a caching mechanism for frequently accessed resources. This improves performance by reducing the number of disk reads and API calls.\n\nTwo types of caches are used:\n- `csvCache`: For caching CSV content (10 minutes TTL)\n- `metadataCache`: For caching metadata (30 minutes TTL)\n\nThe caching system automatically handles cache invalidation based on TTL (Time To Live) values and implements a simple LRU (Least Recently Used) strategy to prevent memory issues when dealing with many resources. This ensures optimal performance while maintaining reasonable memory usage.\n\n### Storage Options\n\nThe server supports two storage options:\n\n#### Local Storage\n\nBy default, the server uses local file system storage to store CSV files. This is suitable for most use cases and provides good performance.\n\nTo configure local storage:\n```bash\n# Using environment variables\nSTORAGE_TYPE=local QUIP_STORAGE_PATH=/path/to/storage npm start\n\n# Using command line arguments\nnpm start -- --storage-type local --storage-path /path/to/storage\n```\n\n#### S3 Storage\n\nFor production deployments or when you need to share data across multiple instances, you can use Amazon S3 storage. This allows you to store CSV files in an S3 bucket.\n\nTo configure S3 storage:\n```bash\n# Using environment variables\nSTORAGE_TYPE=s3 S3_BUCKET=your-bucket-name S3_REGION=us-east-1 npm start\n\n# Using command line arguments\nnpm start -- --storage-type s3 --s3-bucket your-bucket-name --s3-region us-east-1\n```\n\nAdditional S3 configuration options:\n- `S3_PREFIX` / `--s3-prefix`: Prefix for S3 object keys (e.g., \"quip-data/\")\n- `S3_URL_EXPIRATION` / `--s3-url-expiration`: URL expiration in seconds (default: 3600)\n- `USE_PRESIGNED_URLS`: Set to \"true\" to generate presigned HTTPS URLs for direct access to S3 resources\n\n**Presigned S3 URLs**:\nWhen `USE_PRESIGNED_URLS` is set to \"true\", the server will generate presigned HTTPS URLs for resource URIs instead of s3:// URIs. This allows direct access to the resources without requiring AWS credentials or special S3 client libraries. Presigned URLs are temporary and expire after the time specified by `S3_URL_EXPIRATION` (default: 3600 seconds).\n\n**AWS Authentication**:\nThe S3 storage implementation uses the AWS SDK, which automatically loads credentials from the environment. You can provide AWS credentials using any of the standard methods:\n- Environment variables (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`)\n- Shared credentials file (`~/.aws/credentials`)\n- IAM roles for Amazon EC2 or ECS tasks\n\nFor more information on AWS authentication, see the [AWS SDK documentation](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-credentials-node.html).\n\n## Health Check Endpoint\n\nThe server provides a health check endpoint at `/health` that can be used to monitor the server's status. This endpoint is available when running in HTTP transport mode.\n\nTo access the health check endpoint, send a GET request to `/health`:\n\n```bash\ncurl http://localhost:3000/health\n```\n\nThe endpoint returns a simple JSON response with status \"ok\" when the server is running properly:\n\n```json\n{\n  \"status\": \"ok\"\n}\n```\n\nThis endpoint can be used by monitoring tools or container orchestration systems to check if the server is healthy and ready to handle requests.\n\n## Cloud Deployment\n\n### AWS Lambda + API Gateway\n\nThe Quip MCP server can be deployed as a serverless application using AWS Lambda with API Gateway. This provides a scalable, low-maintenance deployment option with a streamable HTTP interface.\n\nThe project includes an AWS CDK infrastructure setup that automates the deployment of:\n- Lambda function with the Quip MCP server\n- API Gateway endpoint\n- S3 bucket for storing CSV files\n- Secrets Manager for storing sensitive information\n\nFor detailed deployment instructions, architecture overview, and usage information, see the [AWS Lambda Deployment Guide](infrastructure/api-gateway-lambda/README.md) in the infrastructure directory.\n\nTo connect Claude.app to your deployed MCP server, add the following to your Claude settings (after deployment):\n\n```json\n\"mcpServers\": {\n  \"quip-remote\": {\n    \"endpointUrl\": \"https://your-api-gateway-url/mcp\",\n    \"headers\": {\n      \"X-API-Key\": \"YOUR_API_KEY_VALUE\"\n    }\n  }\n}\n```\n\n### AWS Agent Core Runtime\n\nThe Quip MCP server can also be deployed to AWS Agent Core Runtime, which provides enhanced capabilities for AI agents and MCP servers:\n\n**Key Benefits:**\n- **Extended execution time**: Up to 8 hours (vs 15-minute Lambda limit)\n- **Larger payload support**: 100MB payloads (vs 6MB Lambda limit)\n- **Session isolation**: Dedicated microVMs for each user session\n- **Built-in authentication**: Integrated OAuth and identity management\n- **Enhanced observability**: Specialized tracing for agent operations\n- **Consumption-based pricing**: Pay only for actual runtime usage\n\nThe project includes a complete CDK infrastructure setup for Agent Core Runtime deployment:\n\n- ARM64 container deployment with Docker buildx\n- ECR repository with automated image builds\n- IAM roles with AWS-documented permissions for Agent Core Runtime\n- AwsCustomResource for Agent Core Runtime API calls\n- S3 integration for data storage\n- Secrets Manager integration for credentials\n\n**Complete IAM Permission Set:**\nThe deployment automatically creates an execution role with all required permissions per AWS documentation:\n- ECR image access and authentication\n- CloudWatch Logs for runtime logging\n- X-Ray distributed tracing\n- CloudWatch metrics publishing\n- Agent Core Runtime workload identity\n- Bedrock model invocation capabilities\n\nFor detailed deployment instructions, see the [Agent Core Runtime Deployment Guide](infrastructure/agent-core/README.md).\n\nQuick deployment:\n```bash\ncd infrastructure/agent-core\n./deploy.sh --agent-name my-quip-mcp --region us-west-2\n```\n\n## Development\n\n### Project Structure\n\n```\nquip-mcp-server-typescript/\n├── src/\n│   ├── index.ts                 # Main entry point\n│   ├── server.ts                # MCP server implementation\n│   ├── cli.ts                   # Command-line argument handling\n│   ├── quipClient.ts            # Quip API client\n│   ├── mockClient.ts            # Mock Quip client for testing\n│   ├── tools.ts                 # Tool definitions and handlers\n│   ├── storage.ts               # Storage abstraction and implementations\n│   ├── types.ts                 # TypeScript type definitions\n│   ├── version.ts               # Version information\n│   ├── errors.ts                # Error handling\n│   ├── logger.ts                # Structured logging\n│   ├── auth.ts                  # Authentication\n│   └── cache.ts                 # Caching mechanism\n├── tests/\n│   ├── unit/                    # Unit tests\n│   │   ├── server.test.ts\n│   │   ├── quipClient.test.ts\n│   │   ├── tools.test.ts\n│   │   ├── storage.test.ts\n│   │   └── ...\n│   └── e2e/                     # End-to-end tests\n├── infrastructure/              # AWS deployment resources\n│   ├── api-gateway-lambda/      # CDK project for Lambda + API Gateway deployment\n│   │   ├── bin/\n│   │   │   └── app.ts           # CDK app entry point\n│   │   ├── lib/\n│   │   │   └── quip-mcp-server-stack.ts  # Main CDK stack\n│   │   ├── lambda/              # Lambda function code\n│   │   │   ├── run.js           # Lambda handler\n│   │   │   └── package.json\n│   │   ├── package.json\n│   │   ├── tsconfig.json\n│   │   └── README.md            # Lambda + API Gateway deployment guide\n│   └── README.md                # Overview of deployment options\n├── example-client/              # Example MCP client implementation\n│   ├── src/\n│   │   ├── client-common.ts\n│   │   ├── http-client.ts\n│   │   ├── stdio-client.ts\n│   │   └── index.ts\n│   ├── package.json\n│   └── README.md\n├── dist/                        # Compiled JavaScript output\n├── .env.example                 # Example environment variables\n├── .gitignore                   # Git ignore file\n├── jest.config.js               # Jest configuration\n├── tsconfig.json                # TypeScript configuration\n├── package.json                 # npm package configuration\n└── LICENSE                      # License file\n```\n\n### Setting Up a Development Environment\n\n```bash\n# Clone the repository\ngit clone https://github.com/zxkane/quip-mcp-server-typescript.git\ncd quip-mcp-server-typescript\n\n# Install dependencies\nnpm install\n\n# Build the project\nnpm run build\n\n# Run in development mode\nnpm run dev\n```\n\n### Scripts\n\n- `npm run build`: Build the project\n- `npm start`: Run the server\n- `npm run dev`: Run the server in development mode\n- `npm test`: Run tests\n- `npm run test:watch`: Run tests in watch mode\n- `npm run test:coverage`: Run tests with coverage\n- `npm run test:e2e`: Run end-to-end tests\n- `npm run lint`: Lint the code\n- `npm run format`: Format the code\n\n### Running Tests\n\n```bash\n# Run all tests\nnpm test\n\n# Run tests with coverage\nnpm run test:coverage\n\n# Run tests in watch mode\nnpm run test:watch\n\n# Run end-to-end tests\nnpm run test:e2e\n```\n\n### Debugging\n\nYou can use the MCP inspector to debug the server:\n\n```bash\n# Install the MCP inspector\nnpm install -g @modelcontextprotocol/inspector\n\n# Debug the server\nmcp-inspector node dist/index.js\n```\n\n### Adding New Tools\n\nTo add new tools:\n\n1. Define the tool in `src/tools.ts` by adding it to the `getQuipTools()` function:\n\n```typescript\nexport function getQuipTools(): Tool[] {\n  return [\n    {\n      name: \"quip_read_spreadsheet\",\n      description: \"Read the content of a Quip spreadsheet...\",\n      inputSchema: {\n        // Schema definition\n      }\n    },\n    {\n      name: \"your_new_tool\",\n      description: \"Description of your new tool\",\n      inputSchema: {\n        // Schema definition for your tool\n      }\n    }\n  ];\n}\n```\n\n2. Implement the handler function for the tool:\n\n```typescript\nexport async function handleYourNewTool(\n  args: Record<string, any>,\n  storage: StorageInterface\n): Promise<(TextContent | ImageContent | EmbeddedResource)[]> {\n  // Implement your tool logic here\n  return [{ type: \"text\", text: \"Your tool response\" }];\n}\n```\n\n3. Register the handler in `src/server.ts` by adding it to the `call_tool` handler:\n\n```typescript\nserver.call_tool(async (name: string, arguments_: any) => {\n  logger.info(`Handling tool call: ${name}`);\n  logger.debug(`Tool arguments: ${JSON.stringify(arguments_)}`);\n  \n  if (!arguments_ || typeof arguments_ !== 'object') {\n    logger.error(\"Invalid arguments: not an object\");\n    throw new InvalidParamsError(\"Invalid arguments\");\n  }\n  \n  try {\n    if (name === \"quip_read_spreadsheet\") {\n      if (!storageInstance) {\n        throw new StorageError(\"Storage not initialized\");\n      }\n      return await handleQuipReadSpreadsheet(arguments_, storageInstance, options.mock);\n    } else if (name === \"your_new_tool\") {\n      return await handleYourNewTool(arguments_, storageInstance);\n    } else {\n      logger.error(`Unknown tool: ${name}`);\n      throw new MethodNotFoundError(`Unknown tool: ${name}`);\n    }\n  } catch (error) {\n    if (error instanceof QuipMCPError) {\n      throw error;\n    }\n    const errorMessage = error instanceof Error ? error.message : String(error);\n    logger.error(`Tool call failed: ${errorMessage}`);\n    throw new QuipApiError(`Tool call failed: ${errorMessage}`);\n  }\n});\n```\n\n## Contributing\n\nContributions are welcome! Here's how you can contribute to the project:\n\n1. Fork the repository\n2. Create a new branch (`git checkout -b feature/your-feature-name`)\n3. Make your changes\n4. Run tests to ensure everything works (`npm test`)\n5. Commit your changes (`git commit -m 'Add some feature'`)\n6. Push to the branch (`git push origin feature/your-feature-name`)\n7. Open a Pull Request\n\nPlease make sure your code follows the project's coding standards and includes appropriate tests.\n\n## License\n\n[MIT License](LICENSE)\n","readmeFilename":"README.md"}