@chapterai/mcp 0.1.3 → 0.1.5
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/dist/index.js +50 -25
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22749,20 +22749,24 @@ function registerFileTools(server2) {
|
|
|
22749
22749
|
);
|
|
22750
22750
|
server2.tool(
|
|
22751
22751
|
"read_file",
|
|
22752
|
-
"Read the content of a file in a workspace",
|
|
22752
|
+
"Read the content of a file in a workspace. Use offset/limit to read a slice of a large file instead of the whole thing.",
|
|
22753
22753
|
{
|
|
22754
22754
|
workspaceId: external_exports.string().uuid().optional().describe("Project ID (auto-resolved from workspace link if omitted)"),
|
|
22755
22755
|
workspaceName: external_exports.string().optional().describe("Project name (alternative to workspaceId)"),
|
|
22756
22756
|
path: external_exports.string().describe("File path to read"),
|
|
22757
|
-
ref: external_exports.string().optional().describe("Git ref (branch, tag, or commit SHA)")
|
|
22757
|
+
ref: external_exports.string().optional().describe("Git ref (branch, tag, or commit SHA)"),
|
|
22758
|
+
offset: external_exports.number().int().min(1).optional().describe("1-indexed line number to start reading from (omit to read from line 1)"),
|
|
22759
|
+
limit: external_exports.number().int().min(1).optional().describe("Maximum number of lines to return (omit to read to end of file)")
|
|
22758
22760
|
},
|
|
22759
|
-
async ({ workspaceId, workspaceName, path: path3, ref }) => {
|
|
22761
|
+
async ({ workspaceId, workspaceName, path: path3, ref, offset, limit }) => {
|
|
22760
22762
|
try {
|
|
22761
22763
|
const id = await resolveWorkspaceId(workspaceId, workspaceName);
|
|
22762
22764
|
const result = await api.workspaces.readFile({
|
|
22763
22765
|
workspaceId: id,
|
|
22764
22766
|
path: path3,
|
|
22765
|
-
ref
|
|
22767
|
+
ref,
|
|
22768
|
+
offset,
|
|
22769
|
+
limit
|
|
22766
22770
|
});
|
|
22767
22771
|
return success(result.content);
|
|
22768
22772
|
} catch (error2) {
|
|
@@ -23563,6 +23567,15 @@ ${lines.join("\n")}`);
|
|
|
23563
23567
|
}
|
|
23564
23568
|
|
|
23565
23569
|
// src/tools/intelligence.ts
|
|
23570
|
+
function renderSnippet(snippet) {
|
|
23571
|
+
if (!snippet) return "";
|
|
23572
|
+
const padWidth = Math.max(4, String(snippet.endLine).length);
|
|
23573
|
+
const body = snippet.lines.map((line, i) => `${String(snippet.startLine + i).padStart(padWidth, " ")} | ${line}`).join("\n");
|
|
23574
|
+
return `
|
|
23575
|
+
\`\`\`
|
|
23576
|
+
${body}
|
|
23577
|
+
\`\`\``;
|
|
23578
|
+
}
|
|
23566
23579
|
function registerIntelligenceTools(server2) {
|
|
23567
23580
|
server2.tool(
|
|
23568
23581
|
"scan_codebase",
|
|
@@ -23604,48 +23617,49 @@ function registerIntelligenceTools(server2) {
|
|
|
23604
23617
|
);
|
|
23605
23618
|
server2.tool(
|
|
23606
23619
|
"query_codebase",
|
|
23607
|
-
"Search the codebase index for files, symbols, routes, endpoints, and copy matching a query. Returns ranked results with file paths
|
|
23620
|
+
"Search the codebase index for files, symbols, routes, endpoints, and copy matching a query. Returns ranked results with file paths, line numbers, and inline source snippets so you usually don't need a follow-up read_file call.",
|
|
23608
23621
|
{
|
|
23609
23622
|
workspaceId: external_exports.string().uuid().optional().describe("Workspace ID"),
|
|
23610
23623
|
workspaceName: external_exports.string().optional().describe("Workspace name (alternative to ID)"),
|
|
23611
23624
|
query: external_exports.string().describe('Search query \u2014 e.g. "task creation", "auth middleware", "welcome page"'),
|
|
23612
|
-
limit: external_exports.number().optional().describe("Max results per category (default 20)")
|
|
23625
|
+
limit: external_exports.number().optional().describe("Max results per category (default 20)"),
|
|
23626
|
+
contextLines: external_exports.number().int().min(0).max(20).default(6).describe("Lines of source to include around each hit. 0 disables snippets.")
|
|
23613
23627
|
},
|
|
23614
|
-
async ({ workspaceId, workspaceName, query, limit }) => {
|
|
23628
|
+
async ({ workspaceId, workspaceName, query, limit, contextLines }) => {
|
|
23615
23629
|
try {
|
|
23616
23630
|
const id = await resolveWorkspaceId(workspaceId, workspaceName);
|
|
23617
|
-
const result = await api.intelligence.query({ workspaceId: id, query, limit });
|
|
23631
|
+
const result = await api.intelligence.query({ workspaceId: id, query, limit, contextLines });
|
|
23618
23632
|
const sections = [];
|
|
23619
23633
|
if (result.files.length > 0) {
|
|
23620
23634
|
sections.push("## Files");
|
|
23621
23635
|
for (const f of result.files) {
|
|
23622
23636
|
const exports = f.exports.length > 0 ? ` (exports: ${f.exports.slice(0, 3).join(", ")})` : "";
|
|
23623
|
-
sections.push(`- \`${f.path}\` [${f.category}]${exports}`);
|
|
23637
|
+
sections.push(`- \`${f.path}\` [${f.category}]${exports}${renderSnippet(f.snippet)}`);
|
|
23624
23638
|
}
|
|
23625
23639
|
}
|
|
23626
23640
|
if (result.symbols.length > 0) {
|
|
23627
23641
|
sections.push("\n## Symbols");
|
|
23628
23642
|
for (const s of result.symbols) {
|
|
23629
23643
|
const sig = s.signature ? ` \u2014 \`${s.signature}\`` : "";
|
|
23630
|
-
sections.push(`- \`${s.name}\` (${s.kind}) at \`${s.filePath}:${s.line}\`${sig}`);
|
|
23644
|
+
sections.push(`- \`${s.name}\` (${s.kind}) at \`${s.filePath}:${s.line}\`${sig}${renderSnippet(s.snippet)}`);
|
|
23631
23645
|
}
|
|
23632
23646
|
}
|
|
23633
23647
|
if (result.copy.length > 0) {
|
|
23634
23648
|
sections.push("\n## Copy/Text");
|
|
23635
23649
|
for (const c of result.copy) {
|
|
23636
|
-
sections.push(`- "${c.text}" at \`${c.filePath}:${c.line}\` in ${c.context}`);
|
|
23650
|
+
sections.push(`- "${c.text}" at \`${c.filePath}:${c.line}\` in ${c.context}${renderSnippet(c.snippet)}`);
|
|
23637
23651
|
}
|
|
23638
23652
|
}
|
|
23639
23653
|
if (result.routes.length > 0) {
|
|
23640
23654
|
sections.push("\n## Routes");
|
|
23641
23655
|
for (const r of result.routes) {
|
|
23642
|
-
sections.push(`- ${r.method ?? "ANY"} \`${r.path}\` \u2192 ${r.handler} at \`${r.filePath}:${r.line}
|
|
23656
|
+
sections.push(`- ${r.method ?? "ANY"} \`${r.path}\` \u2192 ${r.handler} at \`${r.filePath}:${r.line}\`${renderSnippet(r.snippet)}`);
|
|
23643
23657
|
}
|
|
23644
23658
|
}
|
|
23645
23659
|
if (result.endpoints.length > 0) {
|
|
23646
23660
|
sections.push("\n## API Endpoints");
|
|
23647
23661
|
for (const e of result.endpoints) {
|
|
23648
|
-
sections.push(`- \`${e.router ? e.router + "." : ""}${e.name}\` (${e.type}) at \`${e.filePath}:${e.line}
|
|
23662
|
+
sections.push(`- \`${e.router ? e.router + "." : ""}${e.name}\` (${e.type}) at \`${e.filePath}:${e.line}\`${renderSnippet(e.snippet)}`);
|
|
23649
23663
|
}
|
|
23650
23664
|
}
|
|
23651
23665
|
if (sections.length === 0) {
|
|
@@ -23659,24 +23673,30 @@ function registerIntelligenceTools(server2) {
|
|
|
23659
23673
|
);
|
|
23660
23674
|
server2.tool(
|
|
23661
23675
|
"find_symbol",
|
|
23662
|
-
"Find a specific function, class, component, type, or other symbol by name. Returns exact file path and
|
|
23676
|
+
"Find a specific function, class, component, type, or other symbol by name. Returns exact file path, line number, and an inline source snippet so the symbol body is right there.",
|
|
23663
23677
|
{
|
|
23664
23678
|
workspaceId: external_exports.string().uuid().optional().describe("Workspace ID"),
|
|
23665
23679
|
workspaceName: external_exports.string().optional().describe("Workspace name (alternative to ID)"),
|
|
23666
23680
|
name: external_exports.string().describe('Symbol name to search for \u2014 e.g. "TaskCreateInline", "authorizeWorkspaceAccess"'),
|
|
23667
|
-
kind: external_exports.string().optional().describe("Filter by kind: function, class, component, type, interface, enum, hook, struct, method")
|
|
23681
|
+
kind: external_exports.string().optional().describe("Filter by kind: function, class, component, type, interface, enum, hook, struct, method"),
|
|
23682
|
+
contextLines: external_exports.number().int().min(0).max(20).default(8).describe("Lines of source to include around each hit. 0 disables snippets.")
|
|
23668
23683
|
},
|
|
23669
|
-
async ({ workspaceId, workspaceName, name, kind }) => {
|
|
23684
|
+
async ({ workspaceId, workspaceName, name, kind, contextLines }) => {
|
|
23670
23685
|
try {
|
|
23671
23686
|
const id = await resolveWorkspaceId(workspaceId, workspaceName);
|
|
23672
|
-
const results = await api.intelligence.findSymbol({
|
|
23687
|
+
const results = await api.intelligence.findSymbol({
|
|
23688
|
+
workspaceId: id,
|
|
23689
|
+
name,
|
|
23690
|
+
kind,
|
|
23691
|
+
contextLines
|
|
23692
|
+
});
|
|
23673
23693
|
if (results.length === 0) {
|
|
23674
23694
|
return success(`No symbol found matching "${name}"${kind ? ` (kind: ${kind})` : ""}`);
|
|
23675
23695
|
}
|
|
23676
23696
|
const lines = results.map((s) => {
|
|
23677
23697
|
const sig = s.signature ? `
|
|
23678
23698
|
${s.signature}` : "";
|
|
23679
|
-
return `- \`${s.name}\` (${s.kind}) at \`${s.filePath}:${s.line}\`${s.exported ? " [exported]" : ""}${sig}`;
|
|
23699
|
+
return `- \`${s.name}\` (${s.kind}) at \`${s.filePath}:${s.line}\`${s.exported ? " [exported]" : ""}${sig}${renderSnippet(s.snippet)}`;
|
|
23680
23700
|
});
|
|
23681
23701
|
return success(`Found ${results.length} match(es):
|
|
23682
23702
|
${lines.join("\n")}`);
|
|
@@ -23687,21 +23707,26 @@ ${lines.join("\n")}`);
|
|
|
23687
23707
|
);
|
|
23688
23708
|
server2.tool(
|
|
23689
23709
|
"find_copy",
|
|
23690
|
-
"Find user-facing text/copy in the codebase by content. Returns the file path, line number,
|
|
23710
|
+
"Find user-facing text/copy in the codebase by content. Returns the file path, line number, surrounding component context, and an inline JSX/template snippet.",
|
|
23691
23711
|
{
|
|
23692
23712
|
workspaceId: external_exports.string().uuid().optional().describe("Workspace ID"),
|
|
23693
23713
|
workspaceName: external_exports.string().optional().describe("Workspace name (alternative to ID)"),
|
|
23694
|
-
text: external_exports.string().describe('Text to search for \u2014 e.g. "Welcome to Chapter", "Sign in", "No tasks yet"')
|
|
23714
|
+
text: external_exports.string().describe('Text to search for \u2014 e.g. "Welcome to Chapter", "Sign in", "No tasks yet"'),
|
|
23715
|
+
contextLines: external_exports.number().int().min(0).max(20).default(4).describe("Lines of source to include around each hit. 0 disables snippets.")
|
|
23695
23716
|
},
|
|
23696
|
-
async ({ workspaceId, workspaceName, text }) => {
|
|
23717
|
+
async ({ workspaceId, workspaceName, text, contextLines }) => {
|
|
23697
23718
|
try {
|
|
23698
23719
|
const id = await resolveWorkspaceId(workspaceId, workspaceName);
|
|
23699
|
-
const results = await api.intelligence.findCopy({
|
|
23720
|
+
const results = await api.intelligence.findCopy({
|
|
23721
|
+
workspaceId: id,
|
|
23722
|
+
text,
|
|
23723
|
+
contextLines
|
|
23724
|
+
});
|
|
23700
23725
|
if (results.length === 0) {
|
|
23701
23726
|
return success(`No copy found matching "${text}"`);
|
|
23702
23727
|
}
|
|
23703
23728
|
const lines = results.map(
|
|
23704
|
-
(c) => `- "${c.text}" at \`${c.filePath}:${c.line}\` in \`${c.context}\` (${c.type})`
|
|
23729
|
+
(c) => `- "${c.text}" at \`${c.filePath}:${c.line}\` in \`${c.context}\` (${c.type})${renderSnippet(c.snippet)}`
|
|
23705
23730
|
);
|
|
23706
23731
|
return success(`Found ${results.length} match(es):
|
|
23707
23732
|
${lines.join("\n")}`);
|
|
@@ -23712,11 +23737,11 @@ ${lines.join("\n")}`);
|
|
|
23712
23737
|
);
|
|
23713
23738
|
server2.tool(
|
|
23714
23739
|
"get_codebase_context",
|
|
23715
|
-
"
|
|
23740
|
+
"Ask a question about the codebase or describe a task \u2014 returns an AI-synthesized answer with specific file paths, function names, and implementation details. The answer is ready to use: start working immediately based on it. Only read files if you need to see exact code not covered in the answer.",
|
|
23716
23741
|
{
|
|
23717
23742
|
workspaceId: external_exports.string().uuid().optional().describe("Workspace ID"),
|
|
23718
23743
|
workspaceName: external_exports.string().optional().describe("Workspace name (alternative to ID)"),
|
|
23719
|
-
taskDescription: external_exports.string().describe('
|
|
23744
|
+
taskDescription: external_exports.string().describe('Question or task description \u2014 e.g. "how does the permission system work?" or "change the welcome message on the home page"')
|
|
23720
23745
|
},
|
|
23721
23746
|
async ({ workspaceId, workspaceName, taskDescription }) => {
|
|
23722
23747
|
try {
|