Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion docs/api/decorator-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,10 @@ class CatalogServer {

Use `"module": "Node16"`, `"moduleResolution": "Node16"`, and
`"experimentalDecorators": true` for a CommonJS consumer so TypeScript selects
the package's CJS declaration condition. The legacy entrypoint supports public
the package's CJS declaration condition. In the same compilation, static imports
of `@theorvane/type-mcp/http` and `@theorvane/type-mcp/langchain` also select
their CJS `.d.cts` declarations; install `@langchain/core` when importing the
LangChain adapter. The legacy entrypoint supports public
instance methods with string names only; parameter, accessor, field, private,
and symbol-named decorators are excluded. Do not mix Stage 3 and legacy
decorators in one TypeScript compilation unit.
Expand Down
7 changes: 4 additions & 3 deletions docs/guides/configuration.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Configuration and compatibility

`@theorvane/type-mcp@0.3.0` is the published TypeScript declaration and runtime package. Configuration determines whether TypeScript emits standard decorators and whether the runtime can resolve the package's ESM/CJS exports; applications configure their own hosting and transport lifecycle around installed MCP adapters.
`@theorvane/type-mcp@0.3.1` is the published TypeScript declaration and runtime package. Configuration determines whether TypeScript emits standard decorators and whether the runtime can resolve the package's ESM/CJS exports; applications configure their own hosting and transport lifecycle around installed MCP adapters.

## Runtime and package manager

Expand Down Expand Up @@ -41,14 +41,15 @@ Projects using Babel, SWC, or another TypeScript transpiler must confirm that th

## ESM and CommonJS

The package exports both ESM and CommonJS entry points:
The package exports ESM and CommonJS runtime and declaration conditions for the root, HTTP, and LangChain entrypoints. Node-aware TypeScript resolution selects the matching declaration form:

| Consumer | Root loading form |
| --- | --- |
| ESM / TypeScript NodeNext | `import { McpServer } from "@theorvane/type-mcp"` |
| CommonJS / TypeScript Node16 | `import { createMcpHandler } from "@theorvane/type-mcp/http"` |
| CommonJS runtime | `const { McpServer } = require("@theorvane/type-mcp")` |

Decorator syntax is compiled by TypeScript before Node loads the module, so the CommonJS form does not remove the requirement for a standard decorator-compatible compiler configuration. Type-only imports should use TypeScript's `import type` form for the public definition interfaces:
For a CommonJS TypeScript project, use both `"module": "Node16"` and `"moduleResolution": "Node16"`; static imports of `@theorvane/type-mcp/http` and `@theorvane/type-mcp/langchain` then select CJS `.d.cts` declarations. `@theorvane/type-mcp/langchain` also requires its optional `@langchain/core` peer at runtime. Decorator syntax is compiled by TypeScript before Node loads the module, so the CommonJS form does not remove the requirement for a standard decorator-compatible compiler configuration. Type-only imports should use TypeScript's `import type` form for the public definition interfaces:

```ts
import type { McpServerDefinition, McpToolOptions } from "@theorvane/type-mcp";
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 25 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@theorvane/type-mcp",
"version": "0.3.0",
"version": "0.3.1",
"description": "Decorator-first TypeScript framework for Model Context Protocol servers",
"repository": {
"type": "git",
Expand All @@ -17,19 +17,34 @@
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs"
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
},
"./http": {
"types": "./dist/http.d.ts",
"import": "./dist/http.js",
"require": "./dist/http.cjs"
"import": {
"types": "./dist/http.d.ts",
"default": "./dist/http.js"
},
"require": {
"types": "./dist/http.d.cts",
"default": "./dist/http.cjs"
}
},
"./langchain": {
"types": "./dist/langchain.d.ts",
"import": "./dist/langchain.js",
"require": "./dist/langchain.cjs"
"import": {
"types": "./dist/langchain.d.ts",
"default": "./dist/langchain.js"
},
"require": {
"types": "./dist/langchain.d.cts",
"default": "./dist/langchain.cjs"
}
},
"./legacy": {
"import": {
Expand Down
3 changes: 2 additions & 1 deletion scripts/verify-legacy-consumer.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ try {
"--no-fund",
tarballPath,
"zod",
"@langchain/core@1.2.3",
"@types/node",
],
consumer,
Expand All @@ -57,7 +58,7 @@ try {
);
writeFileSync(
join(consumer, "server.ts"),
`import { z } from "zod";\nimport { getMcpServerDefinition, McpServer, McpTool } from "@theorvane/type-mcp/legacy";\n\n@McpServer({ name: "legacy-catalog", version: "1.0.0" })\nclass LegacyCatalog {\n @McpTool({ name: "find_product", description: "Finds a product.", input: z.object({ sku: z.string() }) })\n findProduct({ sku }: { readonly sku: string }) { return { sku }; }\n}\n\nconst definition = getMcpServerDefinition(LegacyCatalog);\nif (definition?.tools[0]?.name !== "find_product") throw new Error("Legacy MCP definition was not registered.");\n`,
`import { z } from "zod";\nimport { createMcpHandler } from "@theorvane/type-mcp/http";\nimport { createLangChainTools } from "@theorvane/type-mcp/langchain";\nimport { getMcpServerDefinition, McpServer, McpTool } from "@theorvane/type-mcp/legacy";\n\n@McpServer({ name: "legacy-catalog", version: "1.0.0" })\nclass LegacyCatalog {\n @McpTool({ name: "find_product", description: "Finds a product.", input: z.object({ sku: z.string() }) })\n findProduct({ sku }: { readonly sku: string }) { return { sku }; }\n}\n\nconst definition = getMcpServerDefinition(LegacyCatalog);\nif (definition?.tools[0]?.name !== "find_product") throw new Error("Legacy MCP definition was not registered.");\nif (typeof createMcpHandler !== "function") throw new Error("CJS http export missing.");\nif (typeof createLangChainTools !== "function") throw new Error("CJS langchain export missing.");\n`,
);
run(
resolve(packageRoot, "node_modules/typescript/bin/tsc"),
Expand Down
19 changes: 15 additions & 4 deletions scripts/verify-package-exports.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,27 @@ for (const { key, symbols } of exportsToVerify) {
typeof importExport.types !== "string" ||
typeof requireExport !== "object" ||
requireExport === null ||
typeof requireExport.default !== "string"
typeof requireExport.default !== "string" ||
typeof requireExport.types !== "string"
) {
throw new Error(`${manifest.name}: invalid ${key} export map`);
}

const esmPath = resolve(root, importExport.default);
const cjsPath = resolve(root, requireExport.default);
const typesPath = resolve(root, importExport.types);
await Promise.all([access(esmPath), access(cjsPath), access(typesPath)]);
const cjsTypesPath = resolve(root, requireExport.types);
await Promise.all([
access(esmPath),
access(cjsPath),
access(typesPath),
access(cjsTypesPath),
]);

const [esm, typeDeclarations] = await Promise.all([
const [esm, typeDeclarations, cjsTypeDeclarations] = await Promise.all([
import(pathToFileURL(esmPath).href),
readFile(typesPath, "utf8"),
readFile(cjsTypesPath, "utf8"),
]);
const require = createRequire(manifestPath);
const cjs = require(cjsPath);
Expand All @@ -83,7 +91,10 @@ for (const { key, symbols } of exportsToVerify) {
`${manifest.name}: missing ${key} ${name} runtime export`,
);
}
if (!typeDeclarations.includes(name)) {
if (
!typeDeclarations.includes(name) ||
!cjsTypeDeclarations.includes(name)
) {
throw new Error(`${manifest.name}: missing ${key} ${name} type export`);
}
}
Expand Down
3 changes: 3 additions & 0 deletions scripts/verify-publish-readiness.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,15 @@ for (const expected of [
"dist/index.js",
"dist/index.cjs",
"dist/index.d.ts",
"dist/index.d.cts",
"dist/http.js",
"dist/http.cjs",
"dist/http.d.ts",
"dist/http.d.cts",
"dist/langchain.js",
"dist/langchain.cjs",
"dist/langchain.d.ts",
"dist/langchain.d.cts",
]) {
if (!files.has(expected)) {
throw new Error(`${manifest.name}: tarball is missing ${expected}`);
Expand Down
11 changes: 8 additions & 3 deletions test/langchain-package-contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,14 @@ describe("LangChain adapter package contract", () => {
) as PackageManifest;

expect(manifest.exports?.["./langchain"]).toEqual({
types: "./dist/langchain.d.ts",
import: "./dist/langchain.js",
require: "./dist/langchain.cjs",
import: {
types: "./dist/langchain.d.ts",
default: "./dist/langchain.js",
},
require: {
types: "./dist/langchain.d.cts",
default: "./dist/langchain.cjs",
},
});
expect(manifest.peerDependencies?.["@langchain/core"]).toBe("^1.2.3");
expect(manifest.peerDependenciesMeta?.["@langchain/core"]?.optional).toBe(
Expand Down
Loading