Skip to content

Commit 831581e

Browse files
v0.3.0 (#160)
* feat(create-xmcp-app): Add option to customize initialized components * nextjs adapter to work on any route * update lock * resource metadata * add resource paths & generate resources import cod * injected resources config * export resource metadata * path validation * URI composing logic based on folder convention * remove extra servercapabilities import * loadResources + configure server + nextjs adapter implementation * add resources to examples * create-xmcp-app CLI support for resources (#158) * update create-xmcp-app cli template gen to support resources * initialize resources to true * init-xmcp support for resources (#159) * add resources path and template creation for init-xmcp * fix typo * ensure subdirs are created * resources examples nit --------- Co-authored-by: FranFigueroa <[email protected]>
1 parent cb39cec commit 831581e

File tree

33 files changed

+1124
-57
lines changed

33 files changed

+1124
-57
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { type ResourceMetadata } from "xmcp";
2+
3+
export const metadata: ResourceMetadata = {
4+
name: "app-config",
5+
title: "Application Config",
6+
description: "Application configuration data",
7+
};
8+
9+
export default function handler() {
10+
return "App configuration here";
11+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { z } from "zod";
2+
import { type ResourceMetadata, type InferSchema } from "xmcp";
3+
4+
export const schema = {
5+
owner: z.string().describe("The owner of the repository"),
6+
repo: z.string().describe("The name of the repository"),
7+
};
8+
9+
export const metadata: ResourceMetadata = {
10+
name: "github-repo",
11+
title: "GitHub Repository",
12+
description: "GitHub repository information",
13+
};
14+
15+
export default function handler({ owner, repo }: InferSchema<typeof schema>) {
16+
return `Repository: ${owner}/${repo}`;
17+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { z } from "zod";
2+
import { type ResourceMetadata, type InferSchema } from "xmcp";
3+
4+
export const schema = {
5+
userId: z.string().describe("The ID of the user"),
6+
};
7+
8+
export const metadata: ResourceMetadata = {
9+
name: "user-profile",
10+
title: "User Profile",
11+
description: "User profile information",
12+
};
13+
14+
export default function handler({ userId }: InferSchema<typeof schema>) {
15+
return `Profile data for user ${userId}`;
16+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { type ResourceMetadata } from "xmcp";
2+
3+
export const metadata: ResourceMetadata = {
4+
name: "app-config",
5+
title: "Application Config",
6+
description: "Application configuration data",
7+
};
8+
9+
export default function handler() {
10+
return "App configuration here";
11+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { z } from "zod";
2+
import { type ResourceMetadata, type InferSchema } from "xmcp";
3+
4+
export const schema = {
5+
owner: z.string().describe("The owner of the repository"),
6+
repo: z.string().describe("The name of the repository"),
7+
};
8+
9+
export const metadata: ResourceMetadata = {
10+
name: "github-repo",
11+
title: "GitHub Repository",
12+
description: "GitHub repository information",
13+
};
14+
15+
export default function handler({ owner, repo }: InferSchema<typeof schema>) {
16+
return `Repository: ${owner}/${repo}`;
17+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { z } from "zod";
2+
import { type ResourceMetadata, type InferSchema } from "xmcp";
3+
4+
export const schema = {
5+
userId: z.string().describe("The ID of the user"),
6+
};
7+
8+
export const metadata: ResourceMetadata = {
9+
name: "user-profile",
10+
title: "User Profile",
11+
description: "User profile information",
12+
};
13+
14+
export default function handler({ userId }: InferSchema<typeof schema>) {
15+
return `Profile data for user ${userId}`;
16+
}

packages/create-xmcp-app/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,9 @@
5050
},
5151
"devDependencies": {
5252
"@types/fs-extra": "^11.0.4",
53-
"@types/inquirer": "^9.0.7",
53+
"@types/inquirer": "^9.0.9",
5454
"@types/node": "^20.17.47",
55+
"@types/ora": "^3.1.0",
5556
"typescript": "^5.3.3"
5657
}
5758
}

packages/create-xmcp-app/src/helpers/copy-template.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,28 @@ import fs from "fs-extra";
55
* Copy template files to the project directory, excluding unnecessary files
66
* @param templateDir - Source template directory path
77
* @param projectPath - Destination project directory path
8+
* @param paths - Array of paths to include (tools, prompts, resources)
89
*/
9-
export function copyTemplate(templateDir: string, projectPath: string): void {
10+
export function copyTemplate(
11+
templateDir: string,
12+
projectPath: string,
13+
paths: string[] = ["tools", "prompts", "resources"]
14+
): void {
1015
fs.copySync(templateDir, projectPath, {
1116
filter: (src) => {
1217
const basename = path.basename(src);
18+
const relativePath = path.relative(templateDir, src);
19+
const srcDir = path.dirname(relativePath).split(path.sep)[0];
20+
21+
// Check if this is a source directory that should be included based on user selection
22+
if (srcDir === "src") {
23+
const subDir = relativePath.split(path.sep)[1];
24+
if (subDir === "tools" && !paths.includes("tools")) return false;
25+
if (subDir === "prompts" && !paths.includes("prompts")) return false;
26+
if (subDir === "resources" && !paths.includes("resources"))
27+
return false;
28+
}
29+
1330
return (
1431
// node_modules could be skipped
1532
basename !== "node_modules" &&

packages/create-xmcp-app/src/helpers/create.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ interface ProjectOptions {
1717
transports: string[];
1818
packageVersion: string;
1919
skipInstall?: boolean;
20+
paths?: string[];
2021
}
2122

2223
/**
@@ -39,6 +40,7 @@ export function createProject(options: ProjectOptions): void {
3940
transports,
4041
packageVersion,
4142
skipInstall,
43+
paths = ["tools", "prompts"],
4244
} = options;
4345

4446
// Ensure the project directory exists
@@ -48,13 +50,13 @@ export function createProject(options: ProjectOptions): void {
4850
const templateDir = path.join(__dirname, "../../templates", "typescript");
4951

5052
// Copy template files to project directory
51-
copyTemplate(templateDir, projectPath);
53+
copyTemplate(templateDir, projectPath, paths);
5254

5355
// Rename special files (e.g., _gitignore to .gitignore)
5456
renameFiles(projectPath);
5557

56-
// Generate xmcp.config.ts based on selected transports
57-
generateConfig(projectPath, transports);
58+
// Generate xmcp.config.ts based on selected transports and paths
59+
generateConfig(projectPath, transports, paths);
5860

5961
// Update package.json with project configuration
6062
updatePackageJson(projectPath, projectName, transports);

packages/create-xmcp-app/src/helpers/generate-config.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ import path from "path";
22
import fs from "fs-extra";
33

44
/**
5-
* Generate xmcp.config.ts based on selected transports
5+
* Generate xmcp.config.ts based on selected transports and paths
66
* @param projectPath - Project directory path
77
* @param transports - Array of selected transport types
8+
* @param paths - Array of selected paths (tools, prompts)
89
*/
910
export function generateConfig(
1011
projectPath: string,
11-
transports: string[]
12+
transports: string[],
13+
paths: string[] = ["tools", "prompts", "resources"]
1214
): void {
1315
const hasHttp = transports.includes("http");
1416
const hasStdio = transports.includes("stdio");
@@ -27,6 +29,37 @@ const config: XmcpConfig = {`;
2729
stdio: true,`;
2830
}
2931

32+
// Add paths configuration
33+
configContent += `
34+
paths: {`;
35+
36+
// Add tools path if selected
37+
if (paths.includes("tools")) {
38+
configContent += `
39+
tools: "./src/tools",`;
40+
}
41+
42+
// Add prompts path if selected
43+
if (paths.includes("prompts")) {
44+
configContent += `
45+
prompts: "./src/prompts",`;
46+
}
47+
48+
// Add resources path if selected
49+
if (paths.includes("resources")) {
50+
configContent += `
51+
resources: "./src/resources",`;
52+
}
53+
54+
// Close the paths object
55+
configContent += `
56+
},`;
57+
58+
// Remove trailing comma if present
59+
configContent = configContent.endsWith(",")
60+
? configContent.slice(0, -1)
61+
: configContent;
62+
3063
configContent += `
3164
};
3265

0 commit comments

Comments
 (0)