@shuji-bonji/w3c-mcp 0.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/LICENSE +21 -0
- package/README.ja.md +246 -0
- package/README.md +246 -0
- package/dist/data/loader.d.ts +88 -0
- package/dist/data/loader.d.ts.map +1 -0
- package/dist/data/loader.js +165 -0
- package/dist/data/loader.js.map +1 -0
- package/dist/errors/index.d.ts +50 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +116 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +307 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/index.d.ts +97 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +53 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/tools/get-css.d.ts +30 -0
- package/dist/tools/get-css.d.ts.map +1 -0
- package/dist/tools/get-css.js +99 -0
- package/dist/tools/get-css.js.map +1 -0
- package/dist/tools/get-elements.d.ts +14 -0
- package/dist/tools/get-elements.d.ts.map +1 -0
- package/dist/tools/get-elements.js +56 -0
- package/dist/tools/get-elements.js.map +1 -0
- package/dist/tools/get-pwa-specs.d.ts +10 -0
- package/dist/tools/get-pwa-specs.d.ts.map +1 -0
- package/dist/tools/get-pwa-specs.js +100 -0
- package/dist/tools/get-pwa-specs.js.map +1 -0
- package/dist/tools/get-spec.d.ts +10 -0
- package/dist/tools/get-spec.d.ts.map +1 -0
- package/dist/tools/get-spec.js +58 -0
- package/dist/tools/get-spec.js.map +1 -0
- package/dist/tools/get-webidl.d.ts +9 -0
- package/dist/tools/get-webidl.d.ts.map +1 -0
- package/dist/tools/get-webidl.js +50 -0
- package/dist/tools/get-webidl.js.map +1 -0
- package/dist/tools/list-specs.d.ts +6 -0
- package/dist/tools/list-specs.d.ts.map +1 -0
- package/dist/tools/list-specs.js +38 -0
- package/dist/tools/list-specs.js.map +1 -0
- package/dist/tools/search-specs.d.ts +16 -0
- package/dist/tools/search-specs.d.ts.map +1 -0
- package/dist/tools/search-specs.js +117 -0
- package/dist/tools/search-specs.js.map +1 -0
- package/dist/types/index.d.ts +85 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/logger.d.ts +49 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +113 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data loader for web-specs and webref packages
|
|
3
|
+
*
|
|
4
|
+
* Performance improvements:
|
|
5
|
+
* - Lazy loading with singleton pattern
|
|
6
|
+
* - Promise-based caching to prevent duplicate loads
|
|
7
|
+
* - Parallel loading support
|
|
8
|
+
* - Memory-efficient data structures
|
|
9
|
+
*/
|
|
10
|
+
import { createRequire } from 'module';
|
|
11
|
+
const require = createRequire(import.meta.url);
|
|
12
|
+
// ============================================
|
|
13
|
+
// Singleton cache with Promise-based loading
|
|
14
|
+
// Prevents duplicate loads when multiple requests come in simultaneously
|
|
15
|
+
// ============================================
|
|
16
|
+
let specsPromise = null;
|
|
17
|
+
let idlPromise = null;
|
|
18
|
+
let cssPromise = null;
|
|
19
|
+
let elementsPromise = null;
|
|
20
|
+
// Shortname index for O(1) lookup
|
|
21
|
+
let specsIndex = null;
|
|
22
|
+
let seriesIndex = null;
|
|
23
|
+
/**
|
|
24
|
+
* Load specs with singleton promise pattern
|
|
25
|
+
* Multiple simultaneous calls share the same loading promise
|
|
26
|
+
*/
|
|
27
|
+
export async function loadSpecs() {
|
|
28
|
+
if (!specsPromise) {
|
|
29
|
+
specsPromise = Promise.resolve().then(() => {
|
|
30
|
+
const specs = require('web-specs');
|
|
31
|
+
// Build indices for faster lookup
|
|
32
|
+
buildSpecIndices(specs);
|
|
33
|
+
return specs;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return specsPromise;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Build indices for O(1) spec lookup by shortname
|
|
40
|
+
*/
|
|
41
|
+
function buildSpecIndices(specs) {
|
|
42
|
+
specsIndex = new Map();
|
|
43
|
+
seriesIndex = new Map();
|
|
44
|
+
for (const spec of specs) {
|
|
45
|
+
specsIndex.set(spec.shortname, spec);
|
|
46
|
+
if (spec.series?.shortname) {
|
|
47
|
+
// Only set if not already set (prefer exact match)
|
|
48
|
+
if (!seriesIndex.has(spec.series.shortname)) {
|
|
49
|
+
seriesIndex.set(spec.series.shortname, spec);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Find a spec by shortname - O(1) with index
|
|
56
|
+
*/
|
|
57
|
+
export async function findSpec(shortname) {
|
|
58
|
+
await loadSpecs(); // Ensure indices are built
|
|
59
|
+
// Try exact match first (O(1))
|
|
60
|
+
if (specsIndex?.has(shortname)) {
|
|
61
|
+
return specsIndex.get(shortname);
|
|
62
|
+
}
|
|
63
|
+
// Try series shortname (O(1))
|
|
64
|
+
if (seriesIndex?.has(shortname)) {
|
|
65
|
+
return seriesIndex.get(shortname);
|
|
66
|
+
}
|
|
67
|
+
// Fallback to partial match (O(n) - only when necessary)
|
|
68
|
+
const specs = await loadSpecs();
|
|
69
|
+
return specs.find(s => s.shortname.includes(shortname) ||
|
|
70
|
+
shortname.includes(s.shortname));
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Load WebIDL with singleton promise pattern
|
|
74
|
+
*/
|
|
75
|
+
export async function loadWebIDLRaw() {
|
|
76
|
+
if (!idlPromise) {
|
|
77
|
+
idlPromise = (async () => {
|
|
78
|
+
try {
|
|
79
|
+
const { readFileSync } = await import('fs');
|
|
80
|
+
const webrefIdl = require('@webref/idl');
|
|
81
|
+
const idlFiles = await webrefIdl.listAll();
|
|
82
|
+
const result = {};
|
|
83
|
+
for (const [shortname, file] of Object.entries(idlFiles)) {
|
|
84
|
+
try {
|
|
85
|
+
result[shortname] = readFileSync(file.path, 'utf8');
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// Skip files that can't be read
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
console.error('Error loading raw WebIDL:', error);
|
|
95
|
+
return {};
|
|
96
|
+
}
|
|
97
|
+
})();
|
|
98
|
+
}
|
|
99
|
+
return idlPromise;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Load CSS data with singleton promise pattern
|
|
103
|
+
*/
|
|
104
|
+
export async function loadCSS() {
|
|
105
|
+
if (!cssPromise) {
|
|
106
|
+
cssPromise = (async () => {
|
|
107
|
+
try {
|
|
108
|
+
const webrefCss = require('@webref/css');
|
|
109
|
+
const data = await webrefCss.listAll();
|
|
110
|
+
return data;
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
console.error('Error loading CSS data:', error);
|
|
114
|
+
return { properties: [], functions: [], types: [], selectors: [], atrules: [] };
|
|
115
|
+
}
|
|
116
|
+
})();
|
|
117
|
+
}
|
|
118
|
+
return cssPromise;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Load elements data with singleton promise pattern
|
|
122
|
+
*/
|
|
123
|
+
export async function loadElements() {
|
|
124
|
+
if (!elementsPromise) {
|
|
125
|
+
elementsPromise = (async () => {
|
|
126
|
+
try {
|
|
127
|
+
const webrefElements = require('@webref/elements');
|
|
128
|
+
const data = await webrefElements.listAll();
|
|
129
|
+
return data;
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
console.error('Error loading elements data:', error);
|
|
133
|
+
return {};
|
|
134
|
+
}
|
|
135
|
+
})();
|
|
136
|
+
}
|
|
137
|
+
return elementsPromise;
|
|
138
|
+
}
|
|
139
|
+
// ============================================
|
|
140
|
+
// Preload function for warming up cache
|
|
141
|
+
// ============================================
|
|
142
|
+
/**
|
|
143
|
+
* Preload all data in parallel
|
|
144
|
+
* Call this at server startup for better first-request performance
|
|
145
|
+
*/
|
|
146
|
+
export async function preloadAll() {
|
|
147
|
+
await Promise.all([
|
|
148
|
+
loadSpecs(),
|
|
149
|
+
loadWebIDLRaw(),
|
|
150
|
+
loadCSS(),
|
|
151
|
+
loadElements()
|
|
152
|
+
]);
|
|
153
|
+
}
|
|
154
|
+
// ============================================
|
|
155
|
+
// Cache invalidation (for testing/development)
|
|
156
|
+
// ============================================
|
|
157
|
+
export function clearCache() {
|
|
158
|
+
specsPromise = null;
|
|
159
|
+
idlPromise = null;
|
|
160
|
+
cssPromise = null;
|
|
161
|
+
elementsPromise = null;
|
|
162
|
+
specsIndex = null;
|
|
163
|
+
seriesIndex = null;
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/data/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error classes for W3C MCP Server
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
/**
|
|
6
|
+
* Base class for W3C MCP errors
|
|
7
|
+
*/
|
|
8
|
+
export declare class W3CMCPError extends Error {
|
|
9
|
+
constructor(message: string);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Spec not found error with suggestions
|
|
13
|
+
*/
|
|
14
|
+
export declare class SpecNotFoundError extends W3CMCPError {
|
|
15
|
+
suggestions?: string[];
|
|
16
|
+
constructor(shortname: string, suggestions?: string[]);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* WebIDL not found error
|
|
20
|
+
*/
|
|
21
|
+
export declare class WebIDLNotFoundError extends W3CMCPError {
|
|
22
|
+
constructor(shortname: string);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* CSS data not found error
|
|
26
|
+
*/
|
|
27
|
+
export declare class CSSNotFoundError extends W3CMCPError {
|
|
28
|
+
constructor(spec: string, availableSpecs?: string[]);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Elements data not found error
|
|
32
|
+
*/
|
|
33
|
+
export declare class ElementsNotFoundError extends W3CMCPError {
|
|
34
|
+
constructor(spec: string, availableSpecs?: string[]);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Validation error wrapper
|
|
38
|
+
*/
|
|
39
|
+
export declare class ValidationError extends W3CMCPError {
|
|
40
|
+
zodError: z.ZodError;
|
|
41
|
+
constructor(zodError: z.ZodError);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Format error response for MCP
|
|
45
|
+
*/
|
|
46
|
+
export declare function formatErrorResponse(error: unknown): {
|
|
47
|
+
text: string;
|
|
48
|
+
errorType: string;
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,qBAAa,WAAY,SAAQ,KAAK;gBACxB,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,WAAW;IACzC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;gBAElB,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE;CAQtD;AAED;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,WAAW;gBACtC,SAAS,EAAE,MAAM;CAI9B;AAED;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,WAAW;gBACnC,IAAI,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE;CAOpD;AAED;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,WAAW;gBACxC,IAAI,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE;CAOpD;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,WAAW;IACvC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC;gBAEhB,QAAQ,EAAE,CAAC,CAAC,QAAQ;CAMjC;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CA4CvF"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error classes for W3C MCP Server
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Base class for W3C MCP errors
|
|
6
|
+
*/
|
|
7
|
+
export class W3CMCPError extends Error {
|
|
8
|
+
constructor(message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = 'W3CMCPError';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Spec not found error with suggestions
|
|
15
|
+
*/
|
|
16
|
+
export class SpecNotFoundError extends W3CMCPError {
|
|
17
|
+
suggestions;
|
|
18
|
+
constructor(shortname, suggestions) {
|
|
19
|
+
const message = suggestions?.length
|
|
20
|
+
? `Specification "${shortname}" not found. Did you mean: ${suggestions.join(', ')}?`
|
|
21
|
+
: `Specification "${shortname}" not found.`;
|
|
22
|
+
super(message);
|
|
23
|
+
this.name = 'SpecNotFoundError';
|
|
24
|
+
this.suggestions = suggestions;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* WebIDL not found error
|
|
29
|
+
*/
|
|
30
|
+
export class WebIDLNotFoundError extends W3CMCPError {
|
|
31
|
+
constructor(shortname) {
|
|
32
|
+
super(`WebIDL not found for "${shortname}". This specification might not have WebIDL definitions.`);
|
|
33
|
+
this.name = 'WebIDLNotFoundError';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* CSS data not found error
|
|
38
|
+
*/
|
|
39
|
+
export class CSSNotFoundError extends W3CMCPError {
|
|
40
|
+
constructor(spec, availableSpecs) {
|
|
41
|
+
const message = availableSpecs?.length
|
|
42
|
+
? `CSS data not found for "${spec}". Available CSS specs: ${availableSpecs.slice(0, 10).join(', ')}...`
|
|
43
|
+
: `CSS data not found for "${spec}".`;
|
|
44
|
+
super(message);
|
|
45
|
+
this.name = 'CSSNotFoundError';
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Elements data not found error
|
|
50
|
+
*/
|
|
51
|
+
export class ElementsNotFoundError extends W3CMCPError {
|
|
52
|
+
constructor(spec, availableSpecs) {
|
|
53
|
+
const message = availableSpecs?.length
|
|
54
|
+
? `Elements data not found for "${spec}". Available specs: ${availableSpecs.join(', ')}`
|
|
55
|
+
: `Elements data not found for "${spec}".`;
|
|
56
|
+
super(message);
|
|
57
|
+
this.name = 'ElementsNotFoundError';
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Validation error wrapper
|
|
62
|
+
*/
|
|
63
|
+
export class ValidationError extends W3CMCPError {
|
|
64
|
+
zodError;
|
|
65
|
+
constructor(zodError) {
|
|
66
|
+
const issues = zodError.issues.map(i => `${i.path.join('.')}: ${i.message}`).join('; ');
|
|
67
|
+
super(`Validation error: ${issues}`);
|
|
68
|
+
this.name = 'ValidationError';
|
|
69
|
+
this.zodError = zodError;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Format error response for MCP
|
|
74
|
+
*/
|
|
75
|
+
export function formatErrorResponse(error) {
|
|
76
|
+
if (error instanceof ValidationError) {
|
|
77
|
+
return {
|
|
78
|
+
text: JSON.stringify({
|
|
79
|
+
error: 'ValidationError',
|
|
80
|
+
message: error.message,
|
|
81
|
+
issues: error.zodError.issues
|
|
82
|
+
}, null, 2),
|
|
83
|
+
errorType: 'ValidationError'
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
if (error instanceof SpecNotFoundError) {
|
|
87
|
+
return {
|
|
88
|
+
text: JSON.stringify({
|
|
89
|
+
error: 'SpecNotFoundError',
|
|
90
|
+
message: error.message,
|
|
91
|
+
suggestions: error.suggestions
|
|
92
|
+
}, null, 2),
|
|
93
|
+
errorType: 'SpecNotFoundError'
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
if (error instanceof W3CMCPError) {
|
|
97
|
+
return {
|
|
98
|
+
text: JSON.stringify({
|
|
99
|
+
error: error.name,
|
|
100
|
+
message: error.message
|
|
101
|
+
}, null, 2),
|
|
102
|
+
errorType: error.name
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
if (error instanceof Error) {
|
|
106
|
+
return {
|
|
107
|
+
text: `Error: ${error.message}`,
|
|
108
|
+
errorType: 'Error'
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
text: 'An unknown error occurred',
|
|
113
|
+
errorType: 'UnknownError'
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;GAGG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* W3C MCP Server
|
|
4
|
+
* Provides access to W3C/WHATWG/IETF web specifications via MCP protocol
|
|
5
|
+
*/
|
|
6
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
7
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
8
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
9
|
+
import { listSpecs } from './tools/list-specs.js';
|
|
10
|
+
import { getSpec, getSpecDependencies } from './tools/get-spec.js';
|
|
11
|
+
import { searchSpecs } from './tools/search-specs.js';
|
|
12
|
+
import { getWebIDL, listWebIDLSpecs } from './tools/get-webidl.js';
|
|
13
|
+
import { getCSSProperties, searchCSSProperty, listCSSSpecs } from './tools/get-css.js';
|
|
14
|
+
import { getElements, searchElement, listElementSpecs } from './tools/get-elements.js';
|
|
15
|
+
import { getPwaSpecs, getCorePwaSpecs } from './tools/get-pwa-specs.js';
|
|
16
|
+
import { preloadAll } from './data/loader.js';
|
|
17
|
+
// Validation schemas
|
|
18
|
+
import { ListSpecsSchema, GetSpecSchema, SearchSpecsSchema, GetWebIDLSchema, GetCSSPropertiesSchema, GetElementsSchema, GetPwaSpecsSchema, GetSpecDependenciesSchema, validateInput, } from './schemas/index.js';
|
|
19
|
+
// Error handling
|
|
20
|
+
import { formatErrorResponse, ValidationError } from './errors/index.js';
|
|
21
|
+
// Logging
|
|
22
|
+
import { info, logToolCall, logToolResult, PerformanceTimer } from './utils/logger.js';
|
|
23
|
+
const server = new Server({
|
|
24
|
+
name: 'w3c-mcp',
|
|
25
|
+
version: '0.1.0',
|
|
26
|
+
}, {
|
|
27
|
+
capabilities: {
|
|
28
|
+
tools: {},
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
// Tool definitions
|
|
32
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
33
|
+
tools: [
|
|
34
|
+
{
|
|
35
|
+
name: 'list_w3c_specs',
|
|
36
|
+
description: 'List W3C/WHATWG/IETF web specifications with optional filtering by organization, keyword, or category',
|
|
37
|
+
inputSchema: {
|
|
38
|
+
type: 'object',
|
|
39
|
+
properties: {
|
|
40
|
+
organization: {
|
|
41
|
+
type: 'string',
|
|
42
|
+
enum: ['W3C', 'WHATWG', 'IETF', 'all'],
|
|
43
|
+
description: 'Filter by standards organization',
|
|
44
|
+
},
|
|
45
|
+
keyword: {
|
|
46
|
+
type: 'string',
|
|
47
|
+
description: 'Filter by keyword in title or shortname',
|
|
48
|
+
},
|
|
49
|
+
category: {
|
|
50
|
+
type: 'string',
|
|
51
|
+
description: 'Filter by category (e.g., "browser")',
|
|
52
|
+
},
|
|
53
|
+
limit: {
|
|
54
|
+
type: 'number',
|
|
55
|
+
description: 'Maximum number of results (default: 50)',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'get_w3c_spec',
|
|
62
|
+
description: 'Get detailed information about a specific web specification including URLs, status, repository, and test info',
|
|
63
|
+
inputSchema: {
|
|
64
|
+
type: 'object',
|
|
65
|
+
properties: {
|
|
66
|
+
shortname: {
|
|
67
|
+
type: 'string',
|
|
68
|
+
description: 'Specification shortname (e.g., "service-workers", "appmanifest", "fetch", "dom")',
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
required: ['shortname'],
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: 'search_w3c_specs',
|
|
76
|
+
description: 'Search web specifications by query string, searching in title, shortname, and description',
|
|
77
|
+
inputSchema: {
|
|
78
|
+
type: 'object',
|
|
79
|
+
properties: {
|
|
80
|
+
query: {
|
|
81
|
+
type: 'string',
|
|
82
|
+
description: 'Search query (e.g., "service worker", "manifest", "storage")',
|
|
83
|
+
},
|
|
84
|
+
limit: {
|
|
85
|
+
type: 'number',
|
|
86
|
+
description: 'Maximum number of results (default: 20)',
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
required: ['query'],
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: 'get_webidl',
|
|
94
|
+
description: 'Get WebIDL interface definitions for a specification. WebIDL defines the JavaScript APIs.',
|
|
95
|
+
inputSchema: {
|
|
96
|
+
type: 'object',
|
|
97
|
+
properties: {
|
|
98
|
+
shortname: {
|
|
99
|
+
type: 'string',
|
|
100
|
+
description: 'Specification shortname (e.g., "service-workers", "fetch", "dom")',
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
required: ['shortname'],
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: 'list_webidl_specs',
|
|
108
|
+
description: 'List all specifications that have WebIDL definitions available',
|
|
109
|
+
inputSchema: {
|
|
110
|
+
type: 'object',
|
|
111
|
+
properties: {},
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: 'get_css_properties',
|
|
116
|
+
description: 'Get CSS property definitions from a specific spec or all specs',
|
|
117
|
+
inputSchema: {
|
|
118
|
+
type: 'object',
|
|
119
|
+
properties: {
|
|
120
|
+
spec: {
|
|
121
|
+
type: 'string',
|
|
122
|
+
description: 'Specification shortname (e.g., "css-grid-1", "css-flexbox-1"). If omitted, returns all CSS properties.',
|
|
123
|
+
},
|
|
124
|
+
property: {
|
|
125
|
+
type: 'string',
|
|
126
|
+
description: 'Search for a specific CSS property by name',
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
name: 'list_css_specs',
|
|
133
|
+
description: 'List all CSS specifications that have property definitions available',
|
|
134
|
+
inputSchema: {
|
|
135
|
+
type: 'object',
|
|
136
|
+
properties: {},
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: 'get_html_elements',
|
|
141
|
+
description: 'Get HTML element definitions from a specific spec or all specs',
|
|
142
|
+
inputSchema: {
|
|
143
|
+
type: 'object',
|
|
144
|
+
properties: {
|
|
145
|
+
spec: {
|
|
146
|
+
type: 'string',
|
|
147
|
+
description: 'Specification shortname (e.g., "html", "svg"). If omitted, returns all elements.',
|
|
148
|
+
},
|
|
149
|
+
element: {
|
|
150
|
+
type: 'string',
|
|
151
|
+
description: 'Search for a specific element by name (e.g., "video", "canvas")',
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: 'list_element_specs',
|
|
158
|
+
description: 'List all specifications that have HTML element definitions available',
|
|
159
|
+
inputSchema: {
|
|
160
|
+
type: 'object',
|
|
161
|
+
properties: {},
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
name: 'get_pwa_specs',
|
|
166
|
+
description: 'Get all Progressive Web App (PWA) related specifications including Service Worker, Web App Manifest, Push API, Background Sync, etc.',
|
|
167
|
+
inputSchema: {
|
|
168
|
+
type: 'object',
|
|
169
|
+
properties: {
|
|
170
|
+
coreOnly: {
|
|
171
|
+
type: 'boolean',
|
|
172
|
+
description: 'If true, return only the core PWA specs (Service Worker, Manifest, Push, Notifications)',
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
name: 'get_spec_dependencies',
|
|
179
|
+
description: 'Get dependency information for a specification (which specs it depends on and which depend on it)',
|
|
180
|
+
inputSchema: {
|
|
181
|
+
type: 'object',
|
|
182
|
+
properties: {
|
|
183
|
+
shortname: {
|
|
184
|
+
type: 'string',
|
|
185
|
+
description: 'Specification shortname',
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
required: ['shortname'],
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
],
|
|
192
|
+
}));
|
|
193
|
+
// Tool execution with validation and error handling
|
|
194
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
195
|
+
const { name, arguments: args } = request.params;
|
|
196
|
+
const timer = new PerformanceTimer(`tool:${name}`);
|
|
197
|
+
logToolCall(name, args);
|
|
198
|
+
try {
|
|
199
|
+
let result;
|
|
200
|
+
switch (name) {
|
|
201
|
+
case 'list_w3c_specs': {
|
|
202
|
+
const validation = validateInput(ListSpecsSchema, args);
|
|
203
|
+
if (!validation.success)
|
|
204
|
+
throw new ValidationError(validation.error);
|
|
205
|
+
result = await listSpecs(validation.data);
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
case 'get_w3c_spec': {
|
|
209
|
+
const validation = validateInput(GetSpecSchema, args);
|
|
210
|
+
if (!validation.success)
|
|
211
|
+
throw new ValidationError(validation.error);
|
|
212
|
+
result = await getSpec(validation.data.shortname);
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
case 'search_w3c_specs': {
|
|
216
|
+
const validation = validateInput(SearchSpecsSchema, args);
|
|
217
|
+
if (!validation.success)
|
|
218
|
+
throw new ValidationError(validation.error);
|
|
219
|
+
result = await searchSpecs(validation.data.query, validation.data.limit);
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
case 'get_webidl': {
|
|
223
|
+
const validation = validateInput(GetWebIDLSchema, args);
|
|
224
|
+
if (!validation.success)
|
|
225
|
+
throw new ValidationError(validation.error);
|
|
226
|
+
const idl = await getWebIDL(validation.data.shortname);
|
|
227
|
+
timer.end();
|
|
228
|
+
logToolResult(name, idl.length);
|
|
229
|
+
return { content: [{ type: 'text', text: idl }] };
|
|
230
|
+
}
|
|
231
|
+
case 'list_webidl_specs': {
|
|
232
|
+
result = await listWebIDLSpecs();
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
case 'get_css_properties': {
|
|
236
|
+
const validation = validateInput(GetCSSPropertiesSchema, args);
|
|
237
|
+
if (!validation.success)
|
|
238
|
+
throw new ValidationError(validation.error);
|
|
239
|
+
result = validation.data.property
|
|
240
|
+
? await searchCSSProperty(validation.data.property)
|
|
241
|
+
: await getCSSProperties(validation.data.spec);
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
case 'list_css_specs': {
|
|
245
|
+
result = await listCSSSpecs();
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
case 'get_html_elements': {
|
|
249
|
+
const validation = validateInput(GetElementsSchema, args);
|
|
250
|
+
if (!validation.success)
|
|
251
|
+
throw new ValidationError(validation.error);
|
|
252
|
+
result = validation.data.element
|
|
253
|
+
? await searchElement(validation.data.element)
|
|
254
|
+
: await getElements(validation.data.spec);
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
case 'list_element_specs': {
|
|
258
|
+
result = await listElementSpecs();
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
case 'get_pwa_specs': {
|
|
262
|
+
const validation = validateInput(GetPwaSpecsSchema, args);
|
|
263
|
+
if (!validation.success)
|
|
264
|
+
throw new ValidationError(validation.error);
|
|
265
|
+
result = validation.data.coreOnly ? await getCorePwaSpecs() : await getPwaSpecs();
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
case 'get_spec_dependencies': {
|
|
269
|
+
const validation = validateInput(GetSpecDependenciesSchema, args);
|
|
270
|
+
if (!validation.success)
|
|
271
|
+
throw new ValidationError(validation.error);
|
|
272
|
+
result = await getSpecDependencies(validation.data.shortname);
|
|
273
|
+
break;
|
|
274
|
+
}
|
|
275
|
+
default:
|
|
276
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
277
|
+
}
|
|
278
|
+
const text = JSON.stringify(result, null, 2);
|
|
279
|
+
timer.end();
|
|
280
|
+
logToolResult(name, text.length);
|
|
281
|
+
return { content: [{ type: 'text', text }] };
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
timer.end();
|
|
285
|
+
const formatted = formatErrorResponse(error);
|
|
286
|
+
return {
|
|
287
|
+
content: [{ type: 'text', text: formatted.text }],
|
|
288
|
+
isError: true,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
// Start server
|
|
293
|
+
async function main() {
|
|
294
|
+
info('W3C MCP Server: Preloading data...');
|
|
295
|
+
const timer = new PerformanceTimer('preload');
|
|
296
|
+
await preloadAll();
|
|
297
|
+
const loadTime = timer.end();
|
|
298
|
+
info(`W3C MCP Server: Data loaded in ${loadTime}ms`);
|
|
299
|
+
const transport = new StdioServerTransport();
|
|
300
|
+
await server.connect(transport);
|
|
301
|
+
info('W3C MCP Server running on stdio');
|
|
302
|
+
}
|
|
303
|
+
main().catch((err) => {
|
|
304
|
+
console.error('Failed to start server:', err);
|
|
305
|
+
process.exit(1);
|
|
306
|
+
});
|
|
307
|
+
//# sourceMappingURL=index.js.map
|