@notionhq/notion-mcp-server 1.5.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.dockerignore ADDED
@@ -0,0 +1,3 @@
1
+ node_modules
2
+ Dockerfile
3
+ docker-compose.yml
package/Dockerfile ADDED
@@ -0,0 +1,36 @@
1
+ # syntax=docker/dockerfile:1
2
+
3
+ # Use Node.js LTS as the base image
4
+ FROM node:20-slim AS builder
5
+
6
+ # Set working directory
7
+ WORKDIR /app
8
+
9
+ # Copy package.json and package-lock.json
10
+ COPY package*.json ./
11
+
12
+ # Install dependencies
13
+ RUN --mount=type=cache,target=/root/.npm npm ci --ignore-scripts --omit-dev
14
+
15
+ # Copy source code
16
+ COPY . .
17
+
18
+ # Build the package
19
+ RUN --mount=type=cache,target=/root/.npm npm run build
20
+
21
+ # Install package globally
22
+ RUN --mount=type=cache,target=/root/.npm npm link
23
+
24
+ # Minimal image for runtime
25
+ FROM node:20-slim
26
+
27
+ # Copy built package from builder stage
28
+ COPY scripts/notion-openapi.json /usr/local/scripts/
29
+ COPY --from=builder /usr/local/lib/node_modules/@notionhq/notion-mcp-server /usr/local/lib/node_modules/@notionhq/notion-mcp-server
30
+ COPY --from=builder /usr/local/bin/notion-mcp-server /usr/local/bin/notion-mcp-server
31
+
32
+ # Set default environment variables
33
+ ENV OPENAPI_MCP_HEADERS="{}"
34
+
35
+ # Set entrypoint
36
+ ENTRYPOINT ["notion-mcp-server"]
package/README.md CHANGED
@@ -19,9 +19,17 @@ For example, you can create a read-only integration token by giving only "Read c
19
19
 
20
20
  ![Notion Integration Token Capabilities showing Read content checked](docs/images/integrations-capabilities.png)
21
21
 
22
- #### 2. Adding MCP config to your client:
22
+ #### 2. Connecting content to integration:
23
+ Ensure relevant pages and databases are connected to your integration.
24
+
25
+ To do this, you'll need to visit that page, and click on the 3 dots, and select "Connect to integration".
26
+
27
+ ![Adding Integration Token to Notion Connections](docs/images/connections.png)
23
28
 
24
- Add the following to your `.cursor/mcp.json` or `claude_desktop_config.json` (MacOS: `~/Library/Application\ Support/Claude/claude_desktop_config.json`)
29
+ #### 3. Adding MCP config to your client:
30
+
31
+ ##### Using npm:
32
+ Add the following to your `.cursor/mcp.json` or `claude_desktop_config.json` (MacOS: `~/Library/Application\ Support/Claude/claude_desktop_config.json`)
25
33
 
26
34
  ```javascript
27
35
  {
@@ -37,16 +45,70 @@ For example, you can create a read-only integration token by giving only "Read c
37
45
  }
38
46
  ```
39
47
 
40
- Don't forget to replace `ntn_****` with your integration secret. Find it from your integration configuration tab:
48
+ ##### Using Docker:
41
49
 
42
- ![Copying your Integration token from the Configuration tab in the developer portal](https://github.com/user-attachments/assets/67b44536-5333-49fa-809c-59581bf5370a)
50
+ There are two options for running the MCP server with Docker:
43
51
 
44
- #### 3. Connecting content to integration:
45
- Ensure relevant pages and databases are connected to your integration.
52
+ ###### Option 1: Using the official Docker Hub image:
46
53
 
47
- To do this, you'll need to visit that page, and click on the 3 dots, and select "Connect to integration".
54
+ Add the following to your `.cursor/mcp.json` or `claude_desktop_config.json`:
48
55
 
49
- ![Adding Integration Token to Notion Connections](docs/images/connections.png)
56
+ ```javascript
57
+ {
58
+ "mcpServers": {
59
+ "notionApi": {
60
+ "command": "docker",
61
+ "args": [
62
+ "run",
63
+ "--rm",
64
+ "-i",
65
+ "-e", "OPENAPI_MCP_HEADERS",
66
+ "mcp/notion"
67
+ ],
68
+ "env": {
69
+ "OPENAPI_MCP_HEADERS": "{\"Authorization\":\"Bearer ntn_****\",\"Notion-Version\":\"2022-06-28\"}"
70
+ }
71
+ }
72
+ }
73
+ }
74
+ ```
75
+
76
+ This approach:
77
+ - Uses the official Docker Hub image
78
+ - Properly handles JSON escaping via environment variables
79
+ - Provides a more reliable configuration method
80
+
81
+ ###### Option 2: Building the Docker image locally:
82
+
83
+ You can also build and run the Docker image locally. First, build the Docker image:
84
+
85
+ ```bash
86
+ docker-compose build
87
+ ```
88
+
89
+ Then, add the following to your `.cursor/mcp.json` or `claude_desktop_config.json`:
90
+
91
+ ```javascript
92
+ {
93
+ "mcpServers": {
94
+ "notionApi": {
95
+ "command": "docker",
96
+ "args": [
97
+ "run",
98
+ "--rm",
99
+ "-i",
100
+ "-e",
101
+ "OPENAPI_MCP_HEADERS={\"Authorization\": \"Bearer ntn_****\", \"Notion-Version\": \"2022-06-28\"}",
102
+ "notion-mcp-server"
103
+ ]
104
+ }
105
+ }
106
+ }
107
+ ```
108
+
109
+ Don't forget to replace `ntn_****` with your integration secret. Find it from your integration configuration tab:
110
+
111
+ ![Copying your Integration token from the Configuration tab in the developer portal](https://github.com/user-attachments/assets/67b44536-5333-49fa-809c-59581bf5370a)
50
112
 
51
113
  ### Examples
52
114
 
package/bin/cli.mjs CHANGED
@@ -47,7 +47,7 @@ var Xu=Object.create;var So=Object.defineProperty;var Qu=Object.getOwnPropertyDe
47
47
  `}var hi=class{constructor(t=Yo.stdin,n=Yo.stdout){this._stdin=t,this._stdout=n,this._readBuffer=new fi,this._started=!1,this._ondata=i=>{this._readBuffer.append(i),this.processReadBuffer()},this._onerror=i=>{var a;(a=this.onerror)===null||a===void 0||a.call(this,i)}}async start(){if(this._started)throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");this._started=!0,this._stdin.on("data",this._ondata),this._stdin.on("error",this._onerror)}processReadBuffer(){for(var t,n;;)try{let i=this._readBuffer.readMessage();if(i===null)break;(t=this.onmessage)===null||t===void 0||t.call(this,i)}catch(i){(n=this.onerror)===null||n===void 0||n.call(this,i)}}async close(){var t;this._stdin.off("data",this._ondata),this._stdin.off("error",this._onerror),this._stdin.listenerCount("data")===0&&this._stdin.pause(),this._readBuffer.clear(),(t=this.onclose)===null||t===void 0||t.call(this)}send(t){return new Promise(n=>{let i=Wo(t);this._stdout.write(i)?n():this._stdout.once("drain",n)})}};import S_ from"node:fs";import k_ from"node:path";var af=6e4,xi=class{constructor(t){this._options=t,this._requestMessageId=0,this._requestHandlers=new Map,this._requestHandlerAbortControllers=new Map,this._notificationHandlers=new Map,this._responseHandlers=new Map,this._progressHandlers=new Map,this._timeoutInfo=new Map,this.setNotificationHandler(si,n=>{let i=this._requestHandlerAbortControllers.get(n.params.requestId);i?.abort(n.params.reason)}),this.setNotificationHandler(pi,n=>{this._onprogress(n)}),this.setRequestHandler(ci,n=>({}))}_setupTimeout(t,n,i,a){this._timeoutInfo.set(t,{timeoutId:setTimeout(a,n),startTime:Date.now(),timeout:n,maxTotalTimeout:i,onTimeout:a})}_resetTimeout(t){let n=this._timeoutInfo.get(t);if(!n)return!1;let i=Date.now()-n.startTime;if(n.maxTotalTimeout&&i>=n.maxTotalTimeout)throw this._timeoutInfo.delete(t),new Et(Qe.RequestTimeout,"Maximum total timeout exceeded",{maxTotalTimeout:n.maxTotalTimeout,totalElapsed:i});return clearTimeout(n.timeoutId),n.timeoutId=setTimeout(n.onTimeout,n.timeout),!0}_cleanupTimeout(t){let n=this._timeoutInfo.get(t);n&&(clearTimeout(n.timeoutId),this._timeoutInfo.delete(t))}async connect(t){this._transport=t,this._transport.onclose=()=>{this._onclose()},this._transport.onerror=n=>{this._onerror(n)},this._transport.onmessage=n=>{"method"in n?"id"in n?this._onrequest(n):this._onnotification(n):this._onresponse(n)},await this._transport.start()}_onclose(){var t;let n=this._responseHandlers;this._responseHandlers=new Map,this._progressHandlers.clear(),this._transport=void 0,(t=this.onclose)===null||t===void 0||t.call(this);let i=new Et(Qe.ConnectionClosed,"Connection closed");for(let a of n.values())a(i)}_onerror(t){var n;(n=this.onerror)===null||n===void 0||n.call(this,t)}_onnotification(t){var n;let i=(n=this._notificationHandlers.get(t.method))!==null&&n!==void 0?n:this.fallbackNotificationHandler;i!==void 0&&Promise.resolve().then(()=>i(t)).catch(a=>this._onerror(new Error(`Uncaught error in notification handler: ${a}`)))}_onrequest(t){var n,i,a;let r=(n=this._requestHandlers.get(t.method))!==null&&n!==void 0?n:this.fallbackRequestHandler;if(r===void 0){(i=this._transport)===null||i===void 0||i.send({jsonrpc:"2.0",id:t.id,error:{code:Qe.MethodNotFound,message:"Method not found"}}).catch(p=>this._onerror(new Error(`Failed to send an error response: ${p}`)));return}let o=new AbortController;this._requestHandlerAbortControllers.set(t.id,o);let s={signal:o.signal,sessionId:(a=this._transport)===null||a===void 0?void 0:a.sessionId};Promise.resolve().then(()=>r(t,s)).then(p=>{var c;if(!o.signal.aborted)return(c=this._transport)===null||c===void 0?void 0:c.send({result:p,jsonrpc:"2.0",id:t.id})},p=>{var c,l;if(!o.signal.aborted)return(c=this._transport)===null||c===void 0?void 0:c.send({jsonrpc:"2.0",id:t.id,error:{code:Number.isSafeInteger(p.code)?p.code:Qe.InternalError,message:(l=p.message)!==null&&l!==void 0?l:"Internal error"}})}).catch(p=>this._onerror(new Error(`Failed to send response: ${p}`))).finally(()=>{this._requestHandlerAbortControllers.delete(t.id)})}_onprogress(t){let{progressToken:n,...i}=t.params,a=Number(n),r=this._progressHandlers.get(a);if(!r){this._onerror(new Error(`Received a progress notification for an unknown token: ${JSON.stringify(t)}`));return}let o=this._responseHandlers.get(a);if(this._timeoutInfo.has(a)&&o)try{this._resetTimeout(a)}catch(s){o(s);return}r(i)}_onresponse(t){let n=Number(t.id),i=this._responseHandlers.get(n);if(i===void 0){this._onerror(new Error(`Received a response for an unknown message ID: ${JSON.stringify(t)}`));return}if(this._responseHandlers.delete(n),this._progressHandlers.delete(n),this._cleanupTimeout(n),"result"in t)i(t);else{let a=new Et(t.error.code,t.error.message,t.error.data);i(a)}}get transport(){return this._transport}async close(){var t;await((t=this._transport)===null||t===void 0?void 0:t.close())}request(t,n,i){return new Promise((a,r)=>{var o,s,p,c;if(!this._transport){r(new Error("Not connected"));return}((o=this._options)===null||o===void 0?void 0:o.enforceStrictCapabilities)===!0&&this.assertCapabilityForMethod(t.method),(s=i?.signal)===null||s===void 0||s.throwIfAborted();let l=this._requestMessageId++,d={...t,jsonrpc:"2.0",id:l};i?.onprogress&&(this._progressHandlers.set(l,i.onprogress),d.params={...t.params,_meta:{progressToken:l}});let f=x=>{var g;this._responseHandlers.delete(l),this._progressHandlers.delete(l),this._cleanupTimeout(l),(g=this._transport)===null||g===void 0||g.send({jsonrpc:"2.0",method:"notifications/cancelled",params:{requestId:l,reason:String(x)}}).catch(S=>this._onerror(new Error(`Failed to send cancellation: ${S}`))),r(x)};this._responseHandlers.set(l,x=>{var g;if(!(!((g=i?.signal)===null||g===void 0)&&g.aborted)){if(x instanceof Error)return r(x);try{let S=n.parse(x.result);a(S)}catch(S){r(S)}}}),(p=i?.signal)===null||p===void 0||p.addEventListener("abort",()=>{var x;f((x=i?.signal)===null||x===void 0?void 0:x.reason)});let v=(c=i?.timeout)!==null&&c!==void 0?c:af,h=()=>f(new Et(Qe.RequestTimeout,"Request timed out",{timeout:v}));this._setupTimeout(l,v,i?.maxTotalTimeout,h),this._transport.send(d).catch(x=>{this._cleanupTimeout(l),r(x)})})}async notification(t){if(!this._transport)throw new Error("Not connected");this.assertNotificationCapability(t.method);let n={...t,jsonrpc:"2.0"};await this._transport.send(n)}setRequestHandler(t,n){let i=t.shape.method.value;this.assertRequestHandlerCapability(i),this._requestHandlers.set(i,(a,r)=>Promise.resolve(n(t.parse(a),r)))}removeRequestHandler(t){this._requestHandlers.delete(t)}assertCanSetRequestHandler(t){if(this._requestHandlers.has(t))throw new Error(`A request handler for ${t} already exists, which would be overridden`)}setNotificationHandler(t,n){this._notificationHandlers.set(t.shape.method.value,i=>Promise.resolve(n(t.parse(i))))}removeNotificationHandler(t){this._notificationHandlers.delete(t)}};function Go(e,t){return Object.entries(t).reduce((n,[i,a])=>(a&&typeof a=="object"?n[i]=n[i]?{...n[i],...a}:a:n[i]=a,n),{...e})}var vi=class extends xi{constructor(t,n){var i;super(n),this._serverInfo=t,this._capabilities=(i=n?.capabilities)!==null&&i!==void 0?i:{},this._instructions=n?.instructions,this.setRequestHandler(va,a=>this._oninitialize(a)),this.setNotificationHandler(ga,()=>{var a;return(a=this.oninitialized)===null||a===void 0?void 0:a.call(this)})}registerCapabilities(t){if(this.transport)throw new Error("Cannot register capabilities after connecting to transport");this._capabilities=Go(this._capabilities,t)}assertCapabilityForMethod(t){var n,i;switch(t){case"sampling/createMessage":if(!(!((n=this._clientCapabilities)===null||n===void 0)&&n.sampling))throw new Error(`Client does not support sampling (required for ${t})`);break;case"roots/list":if(!(!((i=this._clientCapabilities)===null||i===void 0)&&i.roots))throw new Error(`Client does not support listing roots (required for ${t})`);break;case"ping":break}}assertNotificationCapability(t){switch(t){case"notifications/message":if(!this._capabilities.logging)throw new Error(`Server does not support logging (required for ${t})`);break;case"notifications/resources/updated":case"notifications/resources/list_changed":if(!this._capabilities.resources)throw new Error(`Server does not support notifying about resources (required for ${t})`);break;case"notifications/tools/list_changed":if(!this._capabilities.tools)throw new Error(`Server does not support notifying of tool list changes (required for ${t})`);break;case"notifications/prompts/list_changed":if(!this._capabilities.prompts)throw new Error(`Server does not support notifying of prompt list changes (required for ${t})`);break;case"notifications/cancelled":break;case"notifications/progress":break}}assertRequestHandlerCapability(t){switch(t){case"sampling/createMessage":if(!this._capabilities.sampling)throw new Error(`Server does not support sampling (required for ${t})`);break;case"logging/setLevel":if(!this._capabilities.logging)throw new Error(`Server does not support logging (required for ${t})`);break;case"prompts/get":case"prompts/list":if(!this._capabilities.prompts)throw new Error(`Server does not support prompts (required for ${t})`);break;case"resources/list":case"resources/templates/list":case"resources/read":if(!this._capabilities.resources)throw new Error(`Server does not support resources (required for ${t})`);break;case"tools/call":case"tools/list":if(!this._capabilities.tools)throw new Error(`Server does not support tools (required for ${t})`);break;case"ping":case"initialize":break}}async _oninitialize(t){let n=t.params.protocolVersion;return this._clientCapabilities=t.params.capabilities,this._clientVersion=t.params.clientInfo,{protocolVersion:Fo.includes(n)?n:xa,capabilities:this.getCapabilities(),serverInfo:this._serverInfo,...this._instructions&&{instructions:this._instructions}}}getClientCapabilities(){return this._clientCapabilities}getClientVersion(){return this._clientVersion}getCapabilities(){return this._capabilities}async ping(){return this.request({method:"ping"},oi)}async createMessage(t,n){return this.request({method:"sampling/createMessage",params:t},_a,n)}async listRoots(t,n){return this.request({method:"roots/list",params:t},wa,n)}async sendLoggingMessage(t){return this.notification({method:"notifications/message",params:t})}async sendResourceUpdated(t){return this.notification({method:"notifications/resources/updated",params:t})}async sendResourceListChanged(){return this.notification({method:"notifications/resources/list_changed"})}async sendToolListChanged(){return this.notification({method:"notifications/tools/list_changed"})}async sendPromptListChanged(){return this.notification({method:"notifications/prompts/list_changed"})}};var gi=class{constructor(t){this.openApiSpec=t;this.schemaCache={};this.nameCounter=0}internalResolveRef(t,n){if(!t.startsWith("#/")||n.has(t))return null;let i=t.replace(/^#\//,"").split("/"),a=this.openApiSpec;for(let r of i)if(a=a[r],!a)return null;return n.add(t),a}convertOpenApiSchemaToJsonSchema(t,n,i=!1){if("$ref"in t){let r=t.$ref;if(!i){if(r.startsWith("#/components/schemas/"))return{$ref:r.replace(/^#\/components\/schemas\//,"#/$defs/"),..."description"in t?{description:t.description}:{}};console.error(`Attempting to resolve ref ${r} not found in components collection.`)}let o={$ref:r};if("description"in t&&t.description&&(o.description=t.description),this.schemaCache[r])return this.schemaCache[r];let s=this.internalResolveRef(r,n);if(s){let p=this.convertOpenApiSchemaToJsonSchema(s,n,i);return this.schemaCache[r]=p,p}else return console.error(`Failed to resolve ref ${r}`),{$ref:r.replace(/^#\/components\/schemas\//,"#/$defs/"),description:"description"in t?t.description??"":""}}let a={};if(t.type&&(a.type=t.type),t.format==="binary"){a.format="uri-reference";let r="absolute paths to local files";a.description=t.description?`${t.description} (${r})`:r}else t.format&&(a.format=t.format),t.description&&(a.description=t.description);if(t.enum&&(a.enum=t.enum),t.default!==void 0&&(a.default=t.default),t.type==="object"){if(a.type="object",t.properties){a.properties={};for(let[r,o]of Object.entries(t.properties))a.properties[r]=this.convertOpenApiSchemaToJsonSchema(o,n,i)}t.required&&(a.required=t.required),t.additionalProperties===!0||t.additionalProperties===void 0?a.additionalProperties=!0:t.additionalProperties&&typeof t.additionalProperties=="object"?a.additionalProperties=this.convertOpenApiSchemaToJsonSchema(t.additionalProperties,n,i):a.additionalProperties=!1}return t.type==="array"&&t.items&&(a.type="array",a.items=this.convertOpenApiSchemaToJsonSchema(t.items,n,i)),t.oneOf&&(a.oneOf=t.oneOf.map(r=>this.convertOpenApiSchemaToJsonSchema(r,n,i))),t.anyOf&&(a.anyOf=t.anyOf.map(r=>this.convertOpenApiSchemaToJsonSchema(r,n,i))),t.allOf&&(a.allOf=t.allOf.map(r=>this.convertOpenApiSchemaToJsonSchema(r,n,i))),a}convertToMCPTools(){let t="API",n={},i={[t]:{methods:[]}},a={};for(let[r,o]of Object.entries(this.openApiSpec.paths||{}))if(o)for(let[s,p]of Object.entries(o)){if(!this.isOperation(s,p))continue;let c=this.convertOperationToMCPMethod(p,s,r);if(c){let l=this.ensureUniqueName(c.name);c.name=l,i[t].methods.push(c),n[t+"-"+l]={...p,method:s,path:r},a[t+"-"+l]={openApi:{...p,method:s,path:r},mcp:c}}}return{tools:i,openApiLookup:n,zip:a}}convertToOpenAITools(){let t=[];for(let[n,i]of Object.entries(this.openApiSpec.paths||{}))if(i)for(let[a,r]of Object.entries(i)){if(!this.isOperation(a,r))continue;let o=this.convertOperationToJsonSchema(r,a,n),s={type:"function",function:{name:r.operationId,description:r.summary||r.description||"",parameters:o}};t.push(s)}return t}convertToAnthropicTools(){let t=[];for(let[n,i]of Object.entries(this.openApiSpec.paths||{}))if(i)for(let[a,r]of Object.entries(i)){if(!this.isOperation(a,r))continue;let o=this.convertOperationToJsonSchema(r,a,n),s={name:r.operationId,description:r.summary||r.description||"",input_schema:o};t.push(s)}return t}convertComponentsToJsonSchema(){let t=this.openApiSpec.components||{},n={};for(let[i,a]of Object.entries(t.schemas||{}))n[i]=this.convertOpenApiSchemaToJsonSchema(a,new Set);return n}convertOperationToJsonSchema(t,n,i){let a={type:"object",properties:{},required:[],$defs:this.convertComponentsToJsonSchema()};if(t.parameters)for(let r of t.parameters){let o=this.resolveParameter(r);if(o&&o.schema){let s=this.convertOpenApiSchemaToJsonSchema(o.schema,new Set);o.description&&(s.description=o.description),a.properties[o.name]=s,o.required&&a.required.push(o.name)}}if(t.requestBody){let r=this.resolveRequestBody(t.requestBody);if(r?.content&&r.content["application/json"]?.schema){let o=this.convertOpenApiSchemaToJsonSchema(r.content["application/json"].schema,new Set);if(o.type==="object"&&o.properties){for(let[s,p]of Object.entries(o.properties))a.properties[s]=p;o.required&&a.required.push(...o.required)}}}return a}isOperation(t,n){return["get","post","put","delete","patch"].includes(t.toLowerCase())}isParameterObject(t){return!("$ref"in t)}isRequestBodyObject(t){return!("$ref"in t)}resolveParameter(t){if(this.isParameterObject(t))return t;{let n=this.internalResolveRef(t.$ref,new Set);if(n&&n.name)return n}return null}resolveRequestBody(t){if(this.isRequestBodyObject(t))return t;{let n=this.internalResolveRef(t.$ref,new Set);if(n)return n}return null}resolveResponse(t){if("$ref"in t){let n=this.internalResolveRef(t.$ref,new Set);return n||null}return t}convertOperationToMCPMethod(t,n,i){if(!t.operationId)return console.warn(`Operation without operationId at ${n} ${i}`),null;let a=t.operationId,r={$defs:this.convertComponentsToJsonSchema(),type:"object",properties:{},required:[]};if(t.parameters)for(let p of t.parameters){let c=this.resolveParameter(p);if(c&&c.schema){let l=this.convertOpenApiSchemaToJsonSchema(c.schema,new Set,!1);c.description&&(l.description=c.description),r.properties[c.name]=l,c.required&&r.required.push(c.name)}}if(t.requestBody){let p=this.resolveRequestBody(t.requestBody);if(p?.content){if(p.content["multipart/form-data"]?.schema){let c=this.convertOpenApiSchemaToJsonSchema(p.content["multipart/form-data"].schema,new Set,!1);if(c.type==="object"&&c.properties){for(let[l,d]of Object.entries(c.properties))r.properties[l]=d;c.required&&r.required.push(...c.required)}}else if(p.content["application/json"]?.schema){let c=this.convertOpenApiSchemaToJsonSchema(p.content["application/json"].schema,new Set,!1);if(c.type==="object"&&c.properties){for(let[l,d]of Object.entries(c.properties))r.properties[l]=d;c.required&&r.required.push(...c.required)}else r.properties.body=c,r.required.push("body")}}}let o=t.summary||t.description||"";if(t.responses){let p=Object.entries(t.responses).filter(([c])=>c.startsWith("4")||c.startsWith("5")).map(([c,l])=>{let f=this.resolveResponse(l)?.description||"";return`${c}: ${f}`});p.length>0&&(o+=`
48
48
  Error Responses:
49
49
  `+p.join(`
50
- `))}let s=this.extractResponseType(t.responses);try{return{name:a,description:o,inputSchema:r,...s?{returnSchema:s}:{}}}catch(p){return console.warn(`Failed to generate Zod schema for ${a}:`,p),{name:a,description:o,inputSchema:r,...s?{returnSchema:s}:{}}}}extractResponseType(t){let n=t?.["200"]||t?.["201"]||t?.["202"]||t?.["204"];if(!n)return null;let i=this.resolveResponse(n);if(!i||!i.content)return null;if(i.content["application/json"]?.schema){let a=this.convertOpenApiSchemaToJsonSchema(i.content["application/json"].schema,new Set,!1);return a.$defs=this.convertComponentsToJsonSchema(),i.description&&!a.description&&(a.description=i.description),a}return i.content["image/png"]||i.content["image/jpeg"]?{type:"string",format:"binary",description:i.description||""}:{type:"string",description:i.description||""}}ensureUniqueName(t){if(t.length<=64)return t;let n=t.slice(0,59),i=this.generateUniqueSuffix();return`${n}-${i}`}generateUniqueSuffix(){return this.nameCounter+=1,this.nameCounter.toString().padStart(4,"0")}};var bo=ko($u(),1),Vu=ko($a(),1);import w_ from"fs";function Hu(e){let t=[];if(!e.requestBody)return t;let a=(e.requestBody.content||{})["multipart/form-data"];if(!a?.schema)return t;let r=a.schema;return r.type!=="object"||!r.properties||Object.entries(r.properties).forEach(([o,s])=>{let p=s;if(p.type==="string"&&p.format==="binary"&&t.push(o),p.type==="array"&&p.items){let c=p.items;c.type==="string"&&c.format==="binary"&&t.push(o)}}),t}var Wn=class extends Error{constructor(n,i,a,r){super(`${i} ${n}`);this.status=i;this.data=a;this.headers=r;this.name="HttpClientError"}},sa=class{constructor(t,n){this.client=new(bo.default.default??bo.default)({definition:n,axiosConfigDefaults:{baseURL:t.baseUrl,headers:{"Content-Type":"application/json","User-Agent":"notion-mcp-server",...t.headers}}}),this.api=this.client.init()}async prepareFileUpload(t,n){console.error("prepareFileUpload",{operation:t,params:n});let i=Hu(t);if(i.length===0)return null;let a=new Vu.default;for(let o of i){let p=function(c,l){try{let d=w_.createReadStream(l);a.append(c,d)}catch(d){throw new Error(`Failed to read file at ${l}: ${d}`)}};var r=p;console.error(`extracting ${o}`,{params:n});let s=n[o];if(!s)throw new Error(`File path must be provided for parameter: ${o}`);switch(typeof s){case"string":p(o,s);break;case"object":if(Array.isArray(s)){let c=0;for(let l of s)p(o,l),c++;break}default:throw new Error(`Unsupported file type: ${typeof s}`)}}for(let[o,s]of Object.entries(n))i.includes(o)||a.append(o,s);return a}async executeOperation(t,n={}){let i=await this.api,a=t.operationId;if(!a)throw new Error("Operation ID is required");let r=await this.prepareFileUpload(t,n),o={},s=r||{...n};if(t.parameters)for(let c of t.parameters)"name"in c&&c.name&&c.in&&(c.in==="path"||c.in==="query")&&n[c.name]!==void 0&&(o[c.name]=n[c.name],r||delete s[c.name]);if(!t.requestBody&&!r)for(let c in s)s[c]!==void 0&&(o[c]=s[c],delete s[c]);let p=i[a];if(!p)throw new Error(`Operation ${a} not found`);try{let c=Object.keys(s).length>0,d={headers:{...r?r.getHeaders():{...c?{"Content-Type":"application/json"}:{"Content-Type":null}}}};console.error("calling operation",{operationId:a,urlParameters:o,bodyParams:s,requestConfig:d});let f=await p(o,c?s:void 0,d),v=new Headers;return Object.entries(f.headers).forEach(([h,x])=>{x&&v.append(h,x.toString())}),{data:f.data,status:f.status,headers:v}}catch(c){if(c.response){console.error("Error in http client",c);let l=new Headers;throw Object.entries(c.response.headers).forEach(([d,f])=>{f&&l.append(d,f.toString())}),new Wn(c.response.statusText||"Request failed",c.response.status,c.response.data,l)}throw c}}};var ca=class{constructor(t,n){this.server=new vi({name:t,version:"1.0.0"},{capabilities:{tools:{}}});let i=n.servers?.[0].url;if(!i)throw new Error("No base URL found in OpenAPI spec");this.httpClient=new sa({baseUrl:i,headers:this.parseHeadersFromEnv()},n);let a=new gi(n),{tools:r,openApiLookup:o}=a.convertToMCPTools();this.tools=r,this.openApiLookup=o,this.setupHandlers()}setupHandlers(){this.server.setRequestHandler(ba,async()=>{let t=[];return Object.entries(this.tools).forEach(([n,i])=>{i.methods.forEach(a=>{let r=`${n}-${a.name}`,o=this.truncateToolName(r);t.push({name:o,description:a.description,inputSchema:a.inputSchema})})}),{tools:t}}),this.server.setRequestHandler(ya,async t=>{console.error("calling tool",t.params);let{name:n,arguments:i}=t.params,a=this.findOperation(n);if(console.error("operations",this.openApiLookup),!a)throw new Error(`Method ${n} not found`);try{let r=await this.httpClient.executeOperation(a,i);return{content:[{type:"text",text:JSON.stringify(r.data)}]}}catch(r){if(console.error("Error in tool call",r),r instanceof Wn){console.error("HttpClientError encountered, returning structured error",r);let o=r.data?.response?.data??r.data??{};return{content:[{type:"text",text:JSON.stringify({status:"error",...typeof o=="object"?o:{data:o}})}]}}throw r}})}findOperation(t){return this.openApiLookup[t]??null}parseHeadersFromEnv(){let t=process.env.OPENAPI_MCP_HEADERS;if(!t)return{};try{let n=JSON.parse(t);return typeof n!="object"||n===null?(console.warn("OPENAPI_MCP_HEADERS environment variable must be a JSON object, got:",typeof n),{}):n}catch(n){return console.warn("Failed to parse OPENAPI_MCP_HEADERS environment variable:",n),{}}}getContentType(t){let n=t.get("content-type");return n?n.includes("text")||n.includes("json")?"text":n.includes("image")?"image":"binary":"binary"}truncateToolName(t){return t.length<=64?t:t.slice(0,64)}async connect(t){await this.server.connect(t)}getServer(){return this.server}};var Yn=class extends Error{constructor(n){super("OpenAPI validation failed");this.errors=n;this.name="ValidationError"}};async function O_(e,t){let n;try{n=S_.readFileSync(k_.resolve(process.cwd(),e),"utf-8")}catch(i){console.error("Failed to read OpenAPI specification file:",i.message),process.exit(1)}try{let i=JSON.parse(n);return t&&(i.servers[0].url=t),i}catch(i){if(i instanceof Yn)throw i;console.error("Failed to parse OpenAPI spec:",i.message),process.exit(1)}}async function Zu(e,t){let n=await O_(e,t);return new ca("Notion API",n)}async function T_(e=process.argv.slice(2)){let t=A_(import.meta.url),n=Ju.dirname(t),i=Ju.resolve(n,"../scripts/notion-openapi.json"),a=process.env.BASE_URL??void 0,r=await Zu(i,a);return await r.connect(new hi),r.getServer()}T_().catch(e=>{e instanceof Yn?(console.error("Invalid OpenAPI 3.1 specification:"),e.errors.forEach(t=>console.error(t))):console.error("Error:",e),process.exit(1)});export{T_ as startServer};
50
+ `))}let s=this.extractResponseType(t.responses);try{return{name:a,description:o,inputSchema:r,...s?{returnSchema:s}:{}}}catch(p){return console.warn(`Failed to generate Zod schema for ${a}:`,p),{name:a,description:o,inputSchema:r,...s?{returnSchema:s}:{}}}}extractResponseType(t){let n=t?.["200"]||t?.["201"]||t?.["202"]||t?.["204"];if(!n)return null;let i=this.resolveResponse(n);if(!i||!i.content)return null;if(i.content["application/json"]?.schema){let a=this.convertOpenApiSchemaToJsonSchema(i.content["application/json"].schema,new Set,!1);return a.$defs=this.convertComponentsToJsonSchema(),i.description&&!a.description&&(a.description=i.description),a}return i.content["image/png"]||i.content["image/jpeg"]?{type:"string",format:"binary",description:i.description||""}:{type:"string",description:i.description||""}}ensureUniqueName(t){if(t.length<=64)return t;let n=t.slice(0,59),i=this.generateUniqueSuffix();return`${n}-${i}`}generateUniqueSuffix(){return this.nameCounter+=1,this.nameCounter.toString().padStart(4,"0")}};var bo=ko($u(),1),Vu=ko($a(),1);import w_ from"fs";function Hu(e){let t=[];if(!e.requestBody)return t;let a=(e.requestBody.content||{})["multipart/form-data"];if(!a?.schema)return t;let r=a.schema;return r.type!=="object"||!r.properties||Object.entries(r.properties).forEach(([o,s])=>{let p=s;if(p.type==="string"&&p.format==="binary"&&t.push(o),p.type==="array"&&p.items){let c=p.items;c.type==="string"&&c.format==="binary"&&t.push(o)}}),t}var Wn=class extends Error{constructor(n,i,a,r){super(`${i} ${n}`);this.status=i;this.data=a;this.headers=r;this.name="HttpClientError"}},sa=class{constructor(t,n){this.client=new(bo.default.default??bo.default)({definition:n,axiosConfigDefaults:{baseURL:t.baseUrl,headers:{"Content-Type":"application/json","User-Agent":"notion-mcp-server",...t.headers}}}),this.api=this.client.init()}async prepareFileUpload(t,n){let i=Hu(t);if(i.length===0)return null;let a=new Vu.default;for(let o of i){let p=function(c,l){try{let d=w_.createReadStream(l);a.append(c,d)}catch(d){throw new Error(`Failed to read file at ${l}: ${d}`)}};var r=p;let s=n[o];if(!s)throw new Error(`File path must be provided for parameter: ${o}`);switch(typeof s){case"string":p(o,s);break;case"object":if(Array.isArray(s)){let c=0;for(let l of s)p(o,l),c++;break}default:throw new Error(`Unsupported file type: ${typeof s}`)}}for(let[o,s]of Object.entries(n))i.includes(o)||a.append(o,s);return a}async executeOperation(t,n={}){let i=await this.api,a=t.operationId;if(!a)throw new Error("Operation ID is required");let r=await this.prepareFileUpload(t,n),o={},s=r||{...n};if(t.parameters)for(let c of t.parameters)"name"in c&&c.name&&c.in&&(c.in==="path"||c.in==="query")&&n[c.name]!==void 0&&(o[c.name]=n[c.name],r||delete s[c.name]);if(!t.requestBody&&!r)for(let c in s)s[c]!==void 0&&(o[c]=s[c],delete s[c]);let p=i[a];if(!p)throw new Error(`Operation ${a} not found`);try{let c=Object.keys(s).length>0,d={headers:{...r?r.getHeaders():{...c?{"Content-Type":"application/json"}:{"Content-Type":null}}}},f=await p(o,c?s:void 0,d),v=new Headers;return Object.entries(f.headers).forEach(([h,x])=>{x&&v.append(h,x.toString())}),{data:f.data,status:f.status,headers:v}}catch(c){if(c.response){console.error("Error in http client",c);let l=new Headers;throw Object.entries(c.response.headers).forEach(([d,f])=>{f&&l.append(d,f.toString())}),new Wn(c.response.statusText||"Request failed",c.response.status,c.response.data,l)}throw c}}};var ca=class{constructor(t,n){this.server=new vi({name:t,version:"1.0.0"},{capabilities:{tools:{}}});let i=n.servers?.[0].url;if(!i)throw new Error("No base URL found in OpenAPI spec");this.httpClient=new sa({baseUrl:i,headers:this.parseHeadersFromEnv()},n);let a=new gi(n),{tools:r,openApiLookup:o}=a.convertToMCPTools();this.tools=r,this.openApiLookup=o,this.setupHandlers()}setupHandlers(){this.server.setRequestHandler(ba,async()=>{let t=[];return Object.entries(this.tools).forEach(([n,i])=>{i.methods.forEach(a=>{let r=`${n}-${a.name}`,o=this.truncateToolName(r);t.push({name:o,description:a.description,inputSchema:a.inputSchema})})}),{tools:t}}),this.server.setRequestHandler(ya,async t=>{let{name:n,arguments:i}=t.params,a=this.findOperation(n);if(!a)throw new Error(`Method ${n} not found`);try{let r=await this.httpClient.executeOperation(a,i);return{content:[{type:"text",text:JSON.stringify(r.data)}]}}catch(r){if(console.error("Error in tool call",r),r instanceof Wn){console.error("HttpClientError encountered, returning structured error",r);let o=r.data?.response?.data??r.data??{};return{content:[{type:"text",text:JSON.stringify({status:"error",...typeof o=="object"?o:{data:o}})}]}}throw r}})}findOperation(t){return this.openApiLookup[t]??null}parseHeadersFromEnv(){let t=process.env.OPENAPI_MCP_HEADERS;if(!t)return{};try{let n=JSON.parse(t);return typeof n!="object"||n===null?(console.warn("OPENAPI_MCP_HEADERS environment variable must be a JSON object, got:",typeof n),{}):n}catch(n){return console.warn("Failed to parse OPENAPI_MCP_HEADERS environment variable:",n),{}}}getContentType(t){let n=t.get("content-type");return n?n.includes("text")||n.includes("json")?"text":n.includes("image")?"image":"binary":"binary"}truncateToolName(t){return t.length<=64?t:t.slice(0,64)}async connect(t){await this.server.connect(t)}getServer(){return this.server}};var Yn=class extends Error{constructor(n){super("OpenAPI validation failed");this.errors=n;this.name="ValidationError"}};async function O_(e,t){let n;try{n=S_.readFileSync(k_.resolve(process.cwd(),e),"utf-8")}catch(i){console.error("Failed to read OpenAPI specification file:",i.message),process.exit(1)}try{let i=JSON.parse(n);return t&&(i.servers[0].url=t),i}catch(i){if(i instanceof Yn)throw i;console.error("Failed to parse OpenAPI spec:",i.message),process.exit(1)}}async function Zu(e,t){let n=await O_(e,t);return new ca("Notion API",n)}async function T_(e=process.argv.slice(2)){let t=A_(import.meta.url),n=Ju.dirname(t),i=Ju.resolve(n,"../scripts/notion-openapi.json"),a=process.env.BASE_URL??void 0,r=await Zu(i,a);return await r.connect(new hi),r.getServer()}T_().catch(e=>{e instanceof Yn?(console.error("Invalid OpenAPI 3.1 specification:"),e.errors.forEach(t=>console.error(t))):console.error("Error:",e),process.exit(1)});export{T_ as startServer};
51
51
  /*! Bundled license information:
52
52
 
53
53
  mime-db/index.js:
@@ -0,0 +1,6 @@
1
+ services:
2
+ notion-mcp-server:
3
+ build: .
4
+ stdin_open: true
5
+ tty: true
6
+ restart: unless-stopped
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "mcp",
7
7
  "server"
8
8
  ],
9
- "version": "1.5.0",
9
+ "version": "1.7.0",
10
10
  "license": "MIT",
11
11
  "type": "module",
12
12
  "scripts": {
@@ -800,13 +800,20 @@
800
800
  "description": "When supplied, orders the results based on the provided [sort criteria](ref:post-database-query-sort).",
801
801
  "items": {
802
802
  "type": "object",
803
- "required": ["property", "direction"],
803
+ "required": [
804
+ "property",
805
+ "direction"
806
+ ],
804
807
  "properties": {
805
808
  "property": {
806
809
  "type": "string"
807
810
  },
808
811
  "direction": {
809
- "enum": ["ascending", "descending"]
812
+ "enum": [
813
+ "ascending",
814
+ "descending"
815
+ ],
816
+ "type": "string"
810
817
  }
811
818
  }
812
819
  }
@@ -964,6 +971,129 @@
964
971
  "properties": {
965
972
  "children": {
966
973
  "type": "array",
974
+ "items": {
975
+ "type": "object",
976
+ "properties": {
977
+ "paragraph": {
978
+ "type": "object",
979
+ "properties": {
980
+ "rich_text": {
981
+ "type": "array",
982
+ "items": {
983
+ "type": "object",
984
+ "properties": {
985
+ "text": {
986
+ "type": "object",
987
+ "properties": {
988
+ "content": {
989
+ "type": "string",
990
+ "maxLength": 2000
991
+ },
992
+ "link": {
993
+ "type": [
994
+ "object",
995
+ "null"
996
+ ],
997
+ "properties": {
998
+ "url": {
999
+ "type": "string"
1000
+ }
1001
+ },
1002
+ "required": [
1003
+ "url"
1004
+ ]
1005
+ }
1006
+ },
1007
+ "additionalProperties": false,
1008
+ "required": [
1009
+ "content"
1010
+ ]
1011
+ },
1012
+ "type": {
1013
+ "enum": [
1014
+ "text"
1015
+ ],
1016
+ "type": "string"
1017
+ }
1018
+ },
1019
+ "additionalProperties": false,
1020
+ "required": [
1021
+ "text"
1022
+ ]
1023
+ },
1024
+ "maxItems": 100
1025
+ }
1026
+ },
1027
+ "additionalProperties": false,
1028
+ "required": [
1029
+ "rich_text"
1030
+ ]
1031
+ },
1032
+ "bulleted_list_item": {
1033
+ "type": "object",
1034
+ "properties": {
1035
+ "rich_text": {
1036
+ "type": "array",
1037
+ "items": {
1038
+ "type": "object",
1039
+ "properties": {
1040
+ "text": {
1041
+ "type": "object",
1042
+ "properties": {
1043
+ "content": {
1044
+ "type": "string",
1045
+ "maxLength": 2000
1046
+ },
1047
+ "link": {
1048
+ "type": [
1049
+ "object",
1050
+ "null"
1051
+ ],
1052
+ "properties": {
1053
+ "url": {
1054
+ "type": "string"
1055
+ }
1056
+ },
1057
+ "required": [
1058
+ "url"
1059
+ ]
1060
+ }
1061
+ },
1062
+ "additionalProperties": false,
1063
+ "required": [
1064
+ "content"
1065
+ ]
1066
+ },
1067
+ "type": {
1068
+ "enum": [
1069
+ "text"
1070
+ ],
1071
+ "type": "string"
1072
+ }
1073
+ },
1074
+ "additionalProperties": false,
1075
+ "required": [
1076
+ "text"
1077
+ ]
1078
+ },
1079
+ "maxItems": 100
1080
+ }
1081
+ },
1082
+ "additionalProperties": false,
1083
+ "required": [
1084
+ "rich_text"
1085
+ ]
1086
+ },
1087
+ "type": {
1088
+ "enum": [
1089
+ "paragraph",
1090
+ "bulleted_list_item"
1091
+ ],
1092
+ "type": "string"
1093
+ }
1094
+ },
1095
+ "additionalProperties": false
1096
+ },
967
1097
  "description": "Child content to append to a container block as an array of [block objects](ref:block)"
968
1098
  },
969
1099
  "after": {
@@ -1126,33 +1256,50 @@
1126
1256
  "maxLength": 2000
1127
1257
  },
1128
1258
  "link": {
1129
- "type": ["object", "null"],
1259
+ "type": [
1260
+ "object",
1261
+ "null"
1262
+ ],
1130
1263
  "properties": {
1131
1264
  "url": {
1132
1265
  "type": "string"
1133
1266
  }
1134
1267
  },
1135
- "required": ["url"]
1268
+ "required": [
1269
+ "url"
1270
+ ]
1136
1271
  }
1137
1272
  },
1138
1273
  "additionalProperties": false,
1139
- "required": ["content"]
1274
+ "required": [
1275
+ "content"
1276
+ ]
1140
1277
  },
1141
1278
  "type": {
1142
- "enum": ["text"]
1279
+ "enum": [
1280
+ "text"
1281
+ ],
1282
+ "type": "string"
1143
1283
  }
1144
1284
  },
1145
1285
  "additionalProperties": false,
1146
- "required": ["text"]
1286
+ "required": [
1287
+ "text"
1288
+ ]
1147
1289
  },
1148
1290
  "maxItems": 100
1149
1291
  },
1150
1292
  "type": {
1151
- "enum": ["title"]
1293
+ "enum": [
1294
+ "title"
1295
+ ],
1296
+ "type": "string"
1152
1297
  }
1153
1298
  },
1154
1299
  "additionalProperties": false,
1155
- "required": ["title"]
1300
+ "required": [
1301
+ "title"
1302
+ ]
1156
1303
  },
1157
1304
  "in_trash": {
1158
1305
  "type": "boolean",
@@ -1171,7 +1318,9 @@
1171
1318
  }
1172
1319
  },
1173
1320
  "additionalProperties": false,
1174
- "required": ["emoji"]
1321
+ "required": [
1322
+ "emoji"
1323
+ ]
1175
1324
  },
1176
1325
  "cover": {
1177
1326
  "type": "object",
@@ -1185,13 +1334,20 @@
1185
1334
  }
1186
1335
  },
1187
1336
  "additionalProperties": false,
1188
- "required": ["url"]
1337
+ "required": [
1338
+ "url"
1339
+ ]
1189
1340
  },
1190
1341
  "type": {
1191
- "enum": ["external"]
1342
+ "enum": [
1343
+ "external"
1344
+ ],
1345
+ "type": "string"
1192
1346
  }
1193
1347
  },
1194
- "required": ["external"],
1348
+ "required": [
1349
+ "external"
1350
+ ],
1195
1351
  "additionalProperties": false
1196
1352
  }
1197
1353
  }
@@ -1228,7 +1384,9 @@
1228
1384
  "format": "uuid"
1229
1385
  }
1230
1386
  },
1231
- "required": ["page_id"]
1387
+ "required": [
1388
+ "page_id"
1389
+ ]
1232
1390
  },
1233
1391
  "properties": {
1234
1392
  "type": "object",
@@ -1237,11 +1395,15 @@
1237
1395
  "type": "array",
1238
1396
  "items": {
1239
1397
  "type": "object",
1240
- "required": ["text"],
1398
+ "required": [
1399
+ "text"
1400
+ ],
1241
1401
  "properties": {
1242
1402
  "text": {
1243
1403
  "type": "object",
1244
- "required": ["content"],
1404
+ "required": [
1405
+ "content"
1406
+ ],
1245
1407
  "properties": {
1246
1408
  "content": {
1247
1409
  "type": "string",
@@ -1254,11 +1416,16 @@
1254
1416
  "maxItems": 100
1255
1417
  },
1256
1418
  "type": {
1257
- "enum": ["title"]
1419
+ "enum": [
1420
+ "title"
1421
+ ],
1422
+ "type": "string"
1258
1423
  }
1259
1424
  },
1260
1425
  "additionalProperties": false,
1261
- "required": ["title"]
1426
+ "required": [
1427
+ "title"
1428
+ ]
1262
1429
  },
1263
1430
  "children": {
1264
1431
  "type": "array",
@@ -1298,20 +1465,29 @@
1298
1465
  "application/json": {
1299
1466
  "schema": {
1300
1467
  "type": "object",
1301
- "required": ["parent","properties"],
1468
+ "required": [
1469
+ "parent",
1470
+ "properties"
1471
+ ],
1302
1472
  "properties": {
1303
1473
  "parent": {
1304
1474
  "type": "object",
1305
1475
  "properties": {
1306
1476
  "type": {
1307
- "enum": ["page_id"]
1477
+ "enum": [
1478
+ "page_id"
1479
+ ],
1480
+ "type": "string"
1308
1481
  },
1309
1482
  "page_id": {
1310
1483
  "type": "string",
1311
1484
  "format": "uuid"
1312
1485
  }
1313
1486
  },
1314
- "required": ["type", "page_id"]
1487
+ "required": [
1488
+ "type",
1489
+ "page_id"
1490
+ ]
1315
1491
  },
1316
1492
  "properties": {
1317
1493
  "type": "object",
@@ -1333,7 +1509,9 @@
1333
1509
  }
1334
1510
  },
1335
1511
  "additionalProperties": false,
1336
- "required": ["title"]
1512
+ "required": [
1513
+ "title"
1514
+ ]
1337
1515
  }
1338
1516
  ]
1339
1517
  }
@@ -1342,7 +1520,9 @@
1342
1520
  "type": "array",
1343
1521
  "items": {
1344
1522
  "type": "object",
1345
- "required": ["text"],
1523
+ "required": [
1524
+ "text"
1525
+ ],
1346
1526
  "properties": {
1347
1527
  "text": {
1348
1528
  "type": "object",
@@ -1352,20 +1532,30 @@
1352
1532
  "maxLength": 2000
1353
1533
  },
1354
1534
  "link": {
1355
- "type": ["object", "null"],
1535
+ "type": [
1536
+ "object",
1537
+ "null"
1538
+ ],
1356
1539
  "properties": {
1357
1540
  "url": {
1358
1541
  "type": "string"
1359
1542
  }
1360
1543
  },
1361
- "required": ["url"]
1544
+ "required": [
1545
+ "url"
1546
+ ]
1362
1547
  }
1363
1548
  },
1364
1549
  "additionalProperties": false,
1365
- "required": ["content"]
1550
+ "required": [
1551
+ "content"
1552
+ ]
1366
1553
  },
1367
1554
  "type": {
1368
- "enum": ["text"]
1555
+ "enum": [
1556
+ "text"
1557
+ ],
1558
+ "type": "string"
1369
1559
  }
1370
1560
  },
1371
1561
  "additionalProperties": false
@@ -1422,7 +1612,9 @@
1422
1612
  "type": "array",
1423
1613
  "items": {
1424
1614
  "type": "object",
1425
- "required": ["text"],
1615
+ "required": [
1616
+ "text"
1617
+ ],
1426
1618
  "properties": {
1427
1619
  "text": {
1428
1620
  "type": "object",
@@ -1432,20 +1624,30 @@
1432
1624
  "maxLength": 2000
1433
1625
  },
1434
1626
  "link": {
1435
- "type": ["object", "null"],
1627
+ "type": [
1628
+ "object",
1629
+ "null"
1630
+ ],
1436
1631
  "properties": {
1437
1632
  "url": {
1438
1633
  "type": "string"
1439
1634
  }
1440
1635
  },
1441
- "required": ["url"]
1636
+ "required": [
1637
+ "url"
1638
+ ]
1442
1639
  }
1443
1640
  },
1444
1641
  "additionalProperties": false,
1445
- "required": ["content"]
1642
+ "required": [
1643
+ "content"
1644
+ ]
1446
1645
  },
1447
1646
  "type": {
1448
- "enum": ["text"]
1647
+ "enum": [
1648
+ "text"
1649
+ ],
1650
+ "type": "string"
1449
1651
  }
1450
1652
  },
1451
1653
  "additionalProperties": false
@@ -1455,7 +1657,9 @@
1455
1657
  "type": "array",
1456
1658
  "items": {
1457
1659
  "type": "object",
1458
- "required": ["text"],
1660
+ "required": [
1661
+ "text"
1662
+ ],
1459
1663
  "properties": {
1460
1664
  "text": {
1461
1665
  "type": "object",
@@ -1465,20 +1669,30 @@
1465
1669
  "maxLength": 2000
1466
1670
  },
1467
1671
  "link": {
1468
- "type": ["object", "null"],
1672
+ "type": [
1673
+ "object",
1674
+ "null"
1675
+ ],
1469
1676
  "properties": {
1470
1677
  "url": {
1471
1678
  "type": "string"
1472
1679
  }
1473
1680
  },
1474
- "required": ["url"]
1681
+ "required": [
1682
+ "url"
1683
+ ]
1475
1684
  }
1476
1685
  },
1477
1686
  "additionalProperties": false,
1478
- "required": ["content"]
1687
+ "required": [
1688
+ "content"
1689
+ ]
1479
1690
  },
1480
1691
  "type": {
1481
- "enum": ["text"]
1692
+ "enum": [
1693
+ "text"
1694
+ ],
1695
+ "type": "string"
1482
1696
  }
1483
1697
  },
1484
1698
  "additionalProperties": false
@@ -1671,7 +1885,9 @@
1671
1885
  "parent": {
1672
1886
  "type": "object",
1673
1887
  "description": "The page that contains the comment",
1674
- "required": ["page_id"],
1888
+ "required": [
1889
+ "page_id"
1890
+ ],
1675
1891
  "properties": {
1676
1892
  "page_id": {
1677
1893
  "type": "string",
@@ -1683,11 +1899,15 @@
1683
1899
  "type": "array",
1684
1900
  "items": {
1685
1901
  "type": "object",
1686
- "required": ["text"],
1902
+ "required": [
1903
+ "text"
1904
+ ],
1687
1905
  "properties": {
1688
1906
  "text": {
1689
1907
  "type": "object",
1690
- "required": ["content"],
1908
+ "required": [
1909
+ "content"
1910
+ ],
1691
1911
  "properties": {
1692
1912
  "content": {
1693
1913
  "type": "string",
@@ -49,7 +49,6 @@ export class HttpClient {
49
49
  }
50
50
 
51
51
  private async prepareFileUpload(operation: OpenAPIV3.OperationObject, params: Record<string, any>): Promise<FormData | null> {
52
- console.error('prepareFileUpload', { operation, params })
53
52
  const fileParams = isFileUploadParameter(operation)
54
53
  if (fileParams.length === 0) return null
55
54
 
@@ -57,7 +56,6 @@ export class HttpClient {
57
56
 
58
57
  // Handle file uploads
59
58
  for (const param of fileParams) {
60
- console.error(`extracting ${param}`, {params})
61
59
  const filePath = params[param]
62
60
  if (!filePath) {
63
61
  throw new Error(`File path must be provided for parameter: ${param}`)
@@ -163,7 +161,6 @@ export class HttpClient {
163
161
  }
164
162
 
165
163
  // first argument is url parameters, second is body parameters
166
- console.error('calling operation', { operationId, urlParameters, bodyParams, requestConfig })
167
164
  const response = await operationFn(urlParameters, hasBody ? bodyParams : undefined, requestConfig)
168
165
 
169
166
  // Convert axios headers to Headers object
@@ -76,12 +76,10 @@ export class MCPProxy {
76
76
 
77
77
  // Handle tool calling
78
78
  this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
79
- console.error('calling tool', request.params)
80
79
  const { name, arguments: params } = request.params
81
80
 
82
81
  // Find the operation in OpenAPI spec
83
82
  const operation = this.findOperation(name)
84
- console.error('operations', this.openApiLookup)
85
83
  if (!operation) {
86
84
  throw new Error(`Method ${name} not found`)
87
85
  }