@notionhq/notion-mcp-server 1.0.0 → 1.1.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/README.md +4 -4
- package/bin/cli.mjs +28 -28
- package/package.json +9 -8
- package/scripts/start-server.ts +17 -59
- package/src/init-server.ts +50 -0
- package/src/openapi-mcp-server/README.md +2 -0
- package/src/openapi-mcp-server/client/http-client.ts +1 -0
- package/src/openapi-mcp-server/mcp/proxy.ts +4 -0
package/package.json
CHANGED
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
"name": "@notionhq/notion-mcp-server",
|
|
3
3
|
"keywords": [
|
|
4
4
|
"notion",
|
|
5
|
+
"api",
|
|
5
6
|
"mcp",
|
|
6
7
|
"server"
|
|
7
8
|
],
|
|
8
|
-
"version": "1.
|
|
9
|
+
"version": "1.1.0",
|
|
9
10
|
"license": "MIT",
|
|
10
11
|
"type": "module",
|
|
11
12
|
"scripts": {
|
|
@@ -17,7 +18,7 @@
|
|
|
17
18
|
},
|
|
18
19
|
"dependencies": {
|
|
19
20
|
"@modelcontextprotocol/sdk": "^1.8.0",
|
|
20
|
-
"axios": "^1.
|
|
21
|
+
"axios": "^1.8.4",
|
|
21
22
|
"express": "^4.21.2",
|
|
22
23
|
"form-data": "^4.0.1",
|
|
23
24
|
"mustache": "^4.2.0",
|
|
@@ -35,13 +36,13 @@
|
|
|
35
36
|
"@types/mustache": "^4.2.5",
|
|
36
37
|
"@types/node": "^20.17.16",
|
|
37
38
|
"@types/which": "^3.0.4",
|
|
38
|
-
"@vitest/coverage-v8": "
|
|
39
|
-
"esbuild": "^0.
|
|
39
|
+
"@vitest/coverage-v8": "3.1.1",
|
|
40
|
+
"esbuild": "^0.25.2",
|
|
40
41
|
"multer": "1.4.5-lts.1",
|
|
41
|
-
"openai": "^4.
|
|
42
|
-
"tsx": "^4.19.
|
|
43
|
-
"typescript": "^5.
|
|
44
|
-
"vitest": "^
|
|
42
|
+
"openai": "^4.91.1",
|
|
43
|
+
"tsx": "^4.19.3",
|
|
44
|
+
"typescript": "^5.8.2",
|
|
45
|
+
"vitest": "^3.1.1"
|
|
45
46
|
},
|
|
46
47
|
"description": "Official MCP server for Notion API",
|
|
47
48
|
"main": "index.js",
|
package/scripts/start-server.ts
CHANGED
|
@@ -1,70 +1,28 @@
|
|
|
1
|
-
import fs from 'node:fs'
|
|
2
1
|
import path from 'node:path'
|
|
3
2
|
import { fileURLToPath } from 'url'
|
|
4
|
-
|
|
5
|
-
import { OpenAPIV3 } from 'openapi-types'
|
|
6
3
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
7
|
-
import OpenAPISchemaValidator from 'openapi-schema-validator'
|
|
8
|
-
|
|
9
|
-
import { MCPProxy } from '../src/openapi-mcp-server/mcp/proxy'
|
|
10
|
-
|
|
11
|
-
export class ValidationError extends Error {
|
|
12
|
-
constructor(public errors: any[]) {
|
|
13
|
-
super('OpenAPI validation failed')
|
|
14
|
-
this.name = 'ValidationError'
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export async function loadOpenApiSpec(specPath: string): Promise<OpenAPIV3.Document> {
|
|
19
|
-
let rawSpec: string
|
|
20
|
-
|
|
21
|
-
try {
|
|
22
|
-
rawSpec = fs.readFileSync(path.resolve(process.cwd(), specPath), 'utf-8')
|
|
23
|
-
} catch (error) {
|
|
24
|
-
console.error('Failed to read OpenAPI specification file:', (error as Error).message)
|
|
25
|
-
process.exit(1)
|
|
26
|
-
}
|
|
27
4
|
|
|
28
|
-
|
|
29
|
-
try {
|
|
30
|
-
const parsed = JSON.parse(rawSpec)
|
|
31
|
-
const baseUrl = process.env.BASE_URL
|
|
5
|
+
import { initProxy, ValidationError } from '../src/init-server'
|
|
32
6
|
|
|
33
|
-
|
|
34
|
-
parsed.servers[0].url = baseUrl
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return parsed as OpenAPIV3.Document
|
|
38
|
-
} catch (error) {
|
|
39
|
-
if (error instanceof ValidationError) {
|
|
40
|
-
throw error
|
|
41
|
-
}
|
|
42
|
-
console.error('Failed to parse OpenAPI specification:', (error as Error).message)
|
|
43
|
-
process.exit(1)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Main execution
|
|
48
|
-
export async function main(args: string[] = process.argv.slice(2)) {
|
|
7
|
+
export async function startServer(args: string[] = process.argv.slice(2)) {
|
|
49
8
|
const filename = fileURLToPath(import.meta.url)
|
|
50
9
|
const directory = path.dirname(filename)
|
|
51
10
|
const specPath = path.resolve(directory, '../scripts/notion-openapi.json')
|
|
52
|
-
|
|
53
|
-
const
|
|
11
|
+
|
|
12
|
+
const baseUrl = process.env.BASE_URL ?? undefined
|
|
54
13
|
|
|
55
|
-
|
|
56
|
-
|
|
14
|
+
const proxy = await initProxy(specPath, baseUrl)
|
|
15
|
+
await proxy.connect(new StdioServerTransport())
|
|
57
16
|
|
|
58
|
-
|
|
59
|
-
// Only run main if this is the entry point
|
|
60
|
-
if (shouldStart) {
|
|
61
|
-
main().catch(error => {
|
|
62
|
-
if (error instanceof ValidationError) {
|
|
63
|
-
console.error('Invalid OpenAPI 3.1 specification:')
|
|
64
|
-
error.errors.forEach(err => console.error(err))
|
|
65
|
-
} else {
|
|
66
|
-
console.error('Error:', error.message)
|
|
67
|
-
}
|
|
68
|
-
process.exit(1)
|
|
69
|
-
})
|
|
17
|
+
return proxy.getServer()
|
|
70
18
|
}
|
|
19
|
+
|
|
20
|
+
startServer().catch(error => {
|
|
21
|
+
if (error instanceof ValidationError) {
|
|
22
|
+
console.error('Invalid OpenAPI 3.1 specification:')
|
|
23
|
+
error.errors.forEach(err => console.error(err))
|
|
24
|
+
} else {
|
|
25
|
+
console.error('Error:', error)
|
|
26
|
+
}
|
|
27
|
+
process.exit(1)
|
|
28
|
+
})
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
|
|
4
|
+
import { OpenAPIV3 } from 'openapi-types'
|
|
5
|
+
import OpenAPISchemaValidator from 'openapi-schema-validator'
|
|
6
|
+
|
|
7
|
+
import { MCPProxy } from './openapi-mcp-server/mcp/proxy'
|
|
8
|
+
|
|
9
|
+
export class ValidationError extends Error {
|
|
10
|
+
constructor(public errors: any[]) {
|
|
11
|
+
super('OpenAPI validation failed')
|
|
12
|
+
this.name = 'ValidationError'
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async function loadOpenApiSpec(specPath: string, baseUrl: string | undefined): Promise<OpenAPIV3.Document> {
|
|
17
|
+
let rawSpec: string
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
rawSpec = fs.readFileSync(path.resolve(process.cwd(), specPath), 'utf-8')
|
|
21
|
+
} catch (error) {
|
|
22
|
+
console.error('Failed to read OpenAPI specification file:', (error as Error).message)
|
|
23
|
+
process.exit(1)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Parse and validate the OpenApi Spec
|
|
27
|
+
try {
|
|
28
|
+
const parsed = JSON.parse(rawSpec)
|
|
29
|
+
|
|
30
|
+
// Override baseUrl if specified.
|
|
31
|
+
if (baseUrl) {
|
|
32
|
+
parsed.servers[0].url = baseUrl
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return parsed as OpenAPIV3.Document
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (error instanceof ValidationError) {
|
|
38
|
+
throw error
|
|
39
|
+
}
|
|
40
|
+
console.error('Failed to parse OpenAPI spec:', (error as Error).message)
|
|
41
|
+
process.exit(1)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function initProxy(specPath: string, baseUrl: string |undefined) {
|
|
46
|
+
const openApiSpec = await loadOpenApiSpec(specPath, baseUrl)
|
|
47
|
+
const proxy = new MCPProxy('Notion API', openApiSpec)
|
|
48
|
+
|
|
49
|
+
return proxy
|
|
50
|
+
}
|