Skip to content

Commit 7ed8941

Browse files
committed
chore(mcp): address review nits (snapshot test, ToolDef, examples)
- Add tools/list + initialize snapshot tests so any future drift between TOOLS, OOXML_TOOL_DEFS, and the docs fails CI. Asserts the 9 expected ooxml_* names in documented order and serverInfo.name === 'ooxml'. - Extract ToolDef interface and annotate both TOOLS and OOXML_TOOL_DEFS so a future field on either array (annotations, outputSchema) widens both consistently. - Restore one prose example query so the /mcp page reads as 1 newcomer prose + 1 implementer prose + 2 schema, not jargon-heavy across the board. - Bump root README MCP server badge from v0.0.1 to v0.14.0. Worker auto-deploy concern (route still pointing at the old name) is acknowledged as a manual route swap on merge per author's call.
1 parent ebdc575 commit 7ed8941

5 files changed

Lines changed: 71 additions & 4 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<img width="300" alt="logo" src="https://github.com/user-attachments/assets/df6311a6-c050-4592-bbf1-4a2228655bc3" />
22

33
[![Web](https://img.shields.io/badge/Web-v0.1.3-blue)](https://ooxml.dev)
4-
[![MCP Server](https://img.shields.io/badge/MCP_Server-v0.0.1-blue)](https://api.ooxml.dev/mcp)
4+
[![MCP Server](https://img.shields.io/badge/MCP_Server-v0.14.0-blue)](https://api.ooxml.dev/mcp)
55
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
66

77
The OOXML spec, explained by people who actually implemented it.

apps/mcp-server/src/mcp.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,20 @@ const PART_DESCRIPTIONS: Record<number, string> = {
3737
4: "Transitional Migration Features",
3838
};
3939

40+
/** Shape of an MCP tool definition. Shared with OOXML_TOOL_DEFS so a future
41+
* field added to one (annotations, outputSchema, etc.) widens both arrays. */
42+
export interface ToolDef {
43+
name: string;
44+
description: string;
45+
inputSchema: {
46+
type: "object";
47+
properties: Record<string, unknown>;
48+
required?: string[];
49+
};
50+
}
51+
4052
// Tool definitions
41-
export const TOOLS = [
53+
export const TOOLS: ToolDef[] = [
4254
{
4355
name: "ooxml_search",
4456
description:

apps/mcp-server/src/ooxml-tools.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*/
1111

1212
import { neon } from "@neondatabase/serverless";
13+
import type { ToolDef } from "./mcp";
1314
import {
1415
type AttrEntry,
1516
type ChildEdge,
@@ -33,7 +34,7 @@ export interface OoxmlEnv {
3334
DATABASE_URL: string;
3435
}
3536

36-
export const OOXML_TOOL_DEFS = [
37+
export const OOXML_TOOL_DEFS: ToolDef[] = [
3738
{
3839
name: "ooxml_element",
3940
description:

apps/web/src/pages/Mcp.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ const SCHEMA_TOOLS = [
5959

6060
const EXAMPLE_QUERIES = [
6161
"How do I add borders to a table cell?",
62-
"What's the difference between w:pPr and w:rPr?",
62+
"How does numbering work in WordprocessingML?",
6363
"What are the legal children of w:CT_Tbl?",
6464
"List all attributes of w:CT_R, including inherited ones.",
6565
];
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* Snapshot the public MCP surface so a future rename or accidental drop
3+
* (between TOOLS, OOXML_TOOL_DEFS, and the docs) fails CI.
4+
*
5+
* No DB access; we exercise tools/list and the initialize handler. tools/call
6+
* is covered by the per-tool tests in ooxml-queries.test.ts.
7+
*/
8+
9+
import { expect, test } from "bun:test";
10+
import { handleMcpRequest } from "../../apps/mcp-server/src/mcp.ts";
11+
12+
const EXPECTED_TOOL_NAMES = [
13+
// Prose search (over the spec PDFs)
14+
"ooxml_search",
15+
"ooxml_section",
16+
"ooxml_parts",
17+
// Schema lookup (over the parsed XSDs)
18+
"ooxml_element",
19+
"ooxml_type",
20+
"ooxml_children",
21+
"ooxml_attributes",
22+
"ooxml_enum",
23+
"ooxml_namespace",
24+
] as const;
25+
26+
interface JsonRpcResponse {
27+
jsonrpc: string;
28+
id: number | string | null;
29+
result?: { tools?: Array<{ name: string }>; serverInfo?: { name: string } };
30+
error?: { code: number; message: string };
31+
}
32+
33+
async function rpc(method: string, params?: unknown): Promise<JsonRpcResponse> {
34+
const req = new Request("https://example.invalid/mcp", {
35+
method: "POST",
36+
headers: { "Content-Type": "application/json" },
37+
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params }),
38+
});
39+
// Env is unused for tools/list and initialize.
40+
const env = { DATABASE_URL: "", VOYAGE_API_KEY: "" } as never;
41+
const res = await handleMcpRequest(req, env);
42+
return (await res.json()) as JsonRpcResponse;
43+
}
44+
45+
test("tools/list returns the full ooxml_* tool set in the documented order", async () => {
46+
const r = await rpc("tools/list");
47+
const names = r.result?.tools?.map((t) => t.name) ?? [];
48+
expect(names).toEqual([...EXPECTED_TOOL_NAMES]);
49+
});
50+
51+
test("initialize advertises serverInfo.name as 'ooxml'", async () => {
52+
const r = await rpc("initialize");
53+
expect(r.result?.serverInfo?.name).toBe("ooxml");
54+
});

0 commit comments

Comments
 (0)