@sudocode-ai/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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 sudocode Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,226 @@
1
+ # Sudocode MCP
2
+
3
+ Model Context Protocol (MCP) server for [sudocode](https://github.com/sudocode-ai/sudocode) - A git-native spec and issue management system designed for AI-assisted development.
4
+
5
+ ## Features
6
+
7
+ - **MCP Tools** for complete issue and spec management
8
+ - **Git-native workflow** - All data stored in git
9
+ - **Anchored feedback** - Link issues to specific lines in specs with smart relocation
10
+ - **Relationship tracking** - Model dependencies and blockers
11
+ - **CLI-first design** - Wraps existing `sudocode` CLI commands
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install -g sudocode
17
+ ```
18
+
19
+ Or to install just the MCP server and CLI:
20
+ ```bash
21
+ npm install -g @sudocode-ai/cli @sudocode-ai/mcp
22
+ ```
23
+
24
+ ## Configuration
25
+
26
+ **IMPORTANT**: Before using this MCP server, sudocode MUST be initialized in your project directory (`sudocode init`)
27
+
28
+ ### First-time setup:
29
+ 1. Navigate to your project root directory
30
+ 2. Run: \`sudocode init\`
31
+ 3. This creates the \`.sudocode/\` directory with necessary database files
32
+ 4. Verify setup: Check that \`.sudocode/cache.db\` exists
33
+
34
+ **Without initialization, all MCP tools will fail with errors.**
35
+
36
+ If you see errors about missing database or .sudocode directory, run \`sudocode init\` first.
37
+
38
+ ### Claude Code
39
+
40
+ **Option 1: Install via Plugin (Recommended)**
41
+
42
+ ```bash
43
+ /plugin marketplace add sudocode-ai/sudocode
44
+ /plugin install sudocode
45
+ ```
46
+
47
+ The plugin handles MCP server setup automatically. See [.claude-plugin/README.md](../.claude-plugin/README.md) for details.
48
+
49
+ **Option 2: Manual MCP Configuration**
50
+
51
+ If you've installed via npm, add to your Claude Code configuration:
52
+
53
+ ```json
54
+ {
55
+ "mcpServers": {
56
+ "sudocode": {
57
+ "command": "sudocode-mcp"
58
+ }
59
+ }
60
+ }
61
+ ```
62
+
63
+ ### Custom Configuration
64
+
65
+ ```json
66
+ {
67
+ "mcpServers": {
68
+ "sudocode": {
69
+ "command": "sudocode-mcp",
70
+ "env": {
71
+ "SUDOCODE_WORKING_DIR": "/path/to/your/project",
72
+ "SUDOCODE_PATH": "sudocode",
73
+ }
74
+ }
75
+ }
76
+ }
77
+ ```
78
+
79
+ ## Environment Variables
80
+
81
+ - `SUDOCODE_PATH` - Path to `sudocode` CLI executable (default: `sudocode`)
82
+ - `SUDOCODE_WORKING_DIR` - Working directory for sudocode (default: current directory)
83
+ - `SUDOCODE_DB` - Custom database path (default: `.sudocode/cache.db`)
84
+ - `SUDOCODE_ACTOR` - Actor name for operations (default: system username)
85
+
86
+ ## Available Tools
87
+
88
+ ### Issue Management
89
+
90
+ - `ready` - Find issues and specs with no blockers
91
+ - `list_issues` - List issues with filters (status, type, priority, assignee)
92
+ - `show_issue` - Show detailed issue information
93
+ - `upsert_issue` - Create/update issue
94
+
95
+ ### Spec Management
96
+
97
+ - `list_specs` - List specs with filters (status, type, priority)
98
+ - `show_spec` - Show detailed spec information with feedback
99
+ - `upsert_spec` - Create/update a specification
100
+
101
+ ### Relationships
102
+
103
+ - `link` - Create relationships between entities (blocks, implements, references, depends-on, parent-child, discovered-from, related)
104
+
105
+ ### Cross-References
106
+
107
+ - `add_reference` - Add inline cross-reference to spec or issue using Obsidian-style `[[ID]]` syntax. Insert references at specific locations (line or text-based) with optional display text and relationship types.
108
+
109
+ ### Feedback System
110
+
111
+ - `upsert_feedback` - Create/update anchored feedback to specs
112
+
113
+ ## Prerequisites
114
+
115
+ You must have the sudocode CLI (aliased `sudocode` or `sdc`) installed and available in your PATH.
116
+
117
+ Install sudocode:
118
+
119
+ ```bash
120
+ npm install -g sudocode
121
+ ```
122
+
123
+ ## Usage Example
124
+
125
+ Once configured in Claude Code, you can ask Claude to:
126
+
127
+ 1. Find ready tasks: "Show me issues that are ready to work on"
128
+ 2. Claim work: "Set issue ISSUE-123 to in_progress status"
129
+ 3. Review specs: "Show me the spec for issue ISSUE-123"
130
+ 4. Add cross-references: "Add a reference to ISSUE-042 in the requirements section of SPEC-010"
131
+ 5. Provide feedback: "Add feedback to spec SPEC-005 about the authentication section"
132
+ 6. Complete work: "Close issue ISSUE-123"
133
+
134
+ ## Development
135
+
136
+ ### Building from Source
137
+
138
+ ```bash
139
+ git clone https://github.com/sudocode-ai/sudocode.git
140
+ cd sudocode/mcp
141
+ npm install
142
+ npm run build # Uses esbuild for bundled & minified output
143
+ ```
144
+
145
+ The build process:
146
+ - Bundles and minifies `src/index.ts` → `dist/index.js` (18 KB)
147
+ - Generates TypeScript declarations
148
+ - Sets executable permissions automatically
149
+
150
+ ### Running Tests
151
+
152
+ ```bash
153
+ npm test # Run all tests in watch mode
154
+ npm test -- --run # Run once
155
+ npm run test:unit # Unit tests only
156
+ ```
157
+
158
+ ### Build Scripts
159
+
160
+ ```bash
161
+ npm run build # Production build (esbuild - bundled & minified)
162
+ npm run build:dev # Development build (tsc - preserves structure)
163
+ npm run dev # Watch mode for development
164
+ npm run clean # Remove build output
165
+ ```
166
+
167
+ ### Project Structure
168
+
169
+ ```
170
+ mcp/
171
+ ├── src/
172
+ │ ├── client.ts # CLI wrapper
173
+ │ ├── server.ts # MCP server
174
+ │ ├── types.ts # Type definitions
175
+ │ └── tools/ # Tool implementations
176
+ │ ├── issues.ts
177
+ │ ├── specs.ts
178
+ │ ├── feedback.ts
179
+ │ ├── relationships.ts
180
+ │ ├── references.ts
181
+ │ ├── analytics.ts
182
+ │ └── init.ts
183
+ ├── tests/
184
+ │ └── unit/ # Unit tests
185
+ └── dist/ # Built output
186
+ ```
187
+
188
+ ## Troubleshooting
189
+
190
+ ### CLI Not Found
191
+
192
+ If you get "CLI not found" errors:
193
+
194
+ 1. Ensure `sudocode` is installed and in your PATH
195
+ 2. Try setting `SUDOCODE_PATH` to the full path of the `sudocode` executable
196
+ 3. Restart Claude Code after configuration changes
197
+
198
+ ### Database Not Found
199
+
200
+ If you get database errors:
201
+
202
+ 1. Run `sudocode init` in your project directory first
203
+ 2. Ensure the working directory is set correctly
204
+ 3. Check that `.sudocode/cache.db` exists
205
+
206
+ ### Permission Errors
207
+
208
+ Ensure you have read/write access to:
209
+
210
+ - The project directory
211
+ - The `.sudocode` directory
212
+ - The database file
213
+
214
+ ## Contributing
215
+
216
+ Contributions are welcome! Please see the main [sudocode repository](https://github.com/sudocode-ai/sudocode) for contribution guidelines.
217
+
218
+ ## License
219
+
220
+ MIT License - see [LICENSE](LICENSE) file for details.
221
+
222
+ ## Links
223
+
224
+ - [sudocode Main Repository](https://github.com/sudocode-ai/sudocode)
225
+ - [Issue Tracker](https://github.com/sudocode-ai/sudocode/issues)
226
+ - [Model Context Protocol](https://modelcontextprotocol.io/)
@@ -0,0 +1,33 @@
1
+ /**
2
+ * sudocode CLI client wrapper
3
+ *
4
+ * This module provides a client class that spawns `sudocode` CLI commands
5
+ * and parses their JSON output for use in MCP tools.
6
+ */
7
+ import { SudocodeClientConfig } from "./types.js";
8
+ export declare class SudocodeClient {
9
+ private workingDir;
10
+ private cliPath;
11
+ private cliArgs;
12
+ private dbPath?;
13
+ private versionChecked;
14
+ constructor(config?: SudocodeClientConfig);
15
+ /**
16
+ * Find the CLI by looking in node_modules/@sudocode-ai/cli
17
+ * Since we added @sudocode-ai/cli as a dependency, it should be there
18
+ */
19
+ private findCliPath;
20
+ /**
21
+ * Execute a CLI command and return parsed JSON output
22
+ */
23
+ exec(args: string[], options?: {
24
+ timeout?: number;
25
+ }): Promise<any>;
26
+ /**
27
+ * Check that the CLI is installed and get its version
28
+ */
29
+ checkVersion(): Promise<{
30
+ version: string;
31
+ }>;
32
+ }
33
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAAE,oBAAoB,EAAiB,MAAM,YAAY,CAAC;AAEjE,qBAAa,cAAc;IACzB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAW;IAC1B,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,cAAc,CAAS;gBAEnB,MAAM,CAAC,EAAE,oBAAoB;IAmBzC;;;OAGG;IACH,OAAO,CAAC,WAAW;IA+CnB;;OAEG;IACG,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IA8FxE;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAyDnD"}
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * sudocode MCP Server entry point
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;GAEG"}
package/dist/index.js ADDED
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+ import{Server as j}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as z}from"@modelcontextprotocol/sdk/server/stdio.js";import{CallToolRequestSchema as $,ListResourcesRequestSchema as N,ListToolsRequestSchema as H,ReadResourceRequestSchema as M}from"@modelcontextprotocol/sdk/types.js";import{spawn as w}from"child_process";import{fileURLToPath as E}from"url";import{dirname as R,join as b}from"path";import{existsSync as O}from"fs";var d=class extends Error{constructor(t,i,s){super(t);this.exitCode=i;this.stderr=s;this.name="SudocodeError"}};var l=class{workingDir;cliPath;cliArgs;dbPath;versionChecked=!1;constructor(e){let t=e?.workingDir||process.env.SUDOCODE_WORKING_DIR||process.cwd();(t==="${workspaceFolder}"||t.includes("${"))&&(t=process.env.PWD||process.cwd()),this.workingDir=t,this.dbPath=e?.dbPath||process.env.SUDOCODE_DB;let i=this.findCliPath();this.cliPath=i.path,this.cliArgs=i.args}findCliPath(){try{let e=E(import.meta.url),t=R(e),i=[b(t,"..","..","node_modules","@sudocode-ai","cli","dist","cli.js"),b(t,"..","node_modules","@sudocode-ai","cli","dist","cli.js")];for(let s of i)if(O(s))return{path:process.execPath,args:[s]}}catch{}return{path:"sudocode",args:[]}}async exec(e,t){this.versionChecked||(await this.checkVersion(),this.versionChecked=!0);let i=[...this.cliArgs,...e];return i.includes("--json")||i.push("--json"),this.dbPath&&!i.includes("--db")&&i.push("--db",this.dbPath),new Promise((s,n)=>{let o=w(this.cliPath,i,{cwd:this.workingDir,env:process.env}),c="",u="";o.stdout.on("data",a=>{c+=a.toString()}),o.stderr.on("data",a=>{u+=a.toString()});let g=t?.timeout||3e4,m=setTimeout(()=>{o.kill(),n(new d(`Command timed out after ${g}ms`,-1,"Timeout"))},g);o.on("close",a=>{if(clearTimeout(m),a!==0){n(new d(`CLI command failed with exit code ${a}`,a||-1,u));return}try{let p=JSON.parse(c);s(p)}catch(p){n(new d(`Failed to parse JSON output: ${p instanceof Error?p.message:String(p)}`,-1,c))}}),o.on("error",a=>{clearTimeout(m),n(new d(`Failed to spawn CLI: ${a.message}`,-1,a.message))})})}async checkVersion(){try{let e=w(this.cliPath,[...this.cliArgs,"--version"],{cwd:this.workingDir}),t="",i="";return e.stdout.on("data",s=>{t+=s.toString()}),e.stderr.on("data",s=>{i+=s.toString()}),new Promise((s,n)=>{e.on("close",o=>{if(o!==0){n(new d("CLI not found or failed to execute. Make sure 'sudocode' is installed and in your PATH.",o||-1,i));return}let c=t.match(/(\d+\.\d+\.\d+)/),u=c?c[1]:t.trim();s({version:u})}),e.on("error",()=>{n(new d(`CLI not found at path: ${this.cliPath}. Make sure 'sudocode' is installed.`,-1,"CLI not found"))})})}catch(e){throw new d(`Failed to check CLI version: ${e instanceof Error?e.message:String(e)}`,-1,"")}}};async function S(r,e={}){let t=await r.exec(["ready"]),i=await r.exec(["status"]);return t.issues&&Array.isArray(t.issues)&&(t.issues=t.issues.map(s=>{let{content:n,...o}=s;return o})),{ready:t,status:i}}async function k(r,e={}){let t=["issue","list"];e.status&&t.push("--status",e.status),e.priority!==void 0&&t.push("--priority",e.priority.toString()),e.limit!==void 0&&t.push("--limit",e.limit.toString()),e.search&&t.push("--grep",e.search);let i=e.archived!==void 0?e.archived:!1;t.push("--archived",i.toString());let s=await r.exec(t);return Array.isArray(s)?s.map(n=>{let{content:o,...c}=n;return c}):s}async function x(r,e){let t=["issue","show",e.issue_id];return r.exec(t)}async function v(r,e){if(!!e.issue_id){let i=["issue","update",e.issue_id];return e.status&&i.push("--status",e.status),e.priority!==void 0&&i.push("--priority",e.priority.toString()),e.title&&i.push("--title",e.title),e.description&&i.push("--description",e.description),e.archived!==void 0&&i.push("--archived",e.archived.toString()),r.exec(i)}else{if(!e.title)throw new Error("title is required when creating a new issue");let i=["issue","create",e.title];return e.description&&i.push("--description",e.description),e.priority!==void 0&&i.push("--priority",e.priority.toString()),e.parent&&i.push("--parent",e.parent),e.tags&&e.tags.length>0&&i.push("--tags",e.tags.join(",")),r.exec(i)}}async function _(r,e={}){let t=["spec","list"];e.limit!==void 0&&t.push("--limit",e.limit.toString()),e.search&&t.push("--grep",e.search);let i=e.archived!==void 0?e.archived:!1;t.push("--archived",i.toString());let s=await r.exec(t);return Array.isArray(s)?s.map(n=>{let{content:o,...c}=n;return c}):s}async function I(r,e){let t=["spec","show",e.spec_id];return r.exec(t)}async function P(r,e){if(!!e.spec_id){let i=["spec","update",e.spec_id];return e.title&&i.push("--title",e.title),e.priority!==void 0&&i.push("--priority",e.priority.toString()),e.description&&i.push("--description",e.description),e.parent!==void 0&&i.push("--parent",e.parent||""),e.tags!==void 0&&i.push("--tags",e.tags.join(",")),e.archived!==void 0&&i.push("--archived",e.archived.toString()),r.exec(i)}else{if(!e.title)throw new Error("title is required when creating a new spec");let i=["spec","create",e.title];return e.priority!==void 0&&i.push("--priority",e.priority.toString()),e.description&&i.push("--description",e.description),e.parent&&i.push("--parent",e.parent),e.tags&&e.tags.length>0&&i.push("--tags",e.tags.join(",")),r.exec(i)}}async function C(r,e){let t=["link",e.from_id,e.to_id];if(e.from_id===e.to_id)throw new Error("from_id and to_id cannot be the same");return e.type&&t.push("--type",e.type),r.exec(t)}async function D(r,e){let t=["feedback","add",e.issue_id,e.spec_id];return t.push("--content",e.content),e.type&&t.push("--type",e.type),e.line!==void 0&&t.push("--line",e.line.toString()),e.text&&t.push("--text",e.text),r.exec(t)}async function T(r,e){let t=i=>{let s=[i,"add-ref",e.entity_id,e.reference_id];return e.line!==void 0&&s.push("--line",e.line.toString()),e.text&&s.push("--text",e.text),e.display_text&&s.push("--display",e.display_text),e.relationship_type&&s.push("--type",e.relationship_type),e.format&&s.push("--format",e.format),e.position&&s.push("--position",e.position),s};try{return await r.exec(t("spec"))}catch{try{return await r.exec(t("issue"))}catch(s){throw s}}}import{existsSync as h}from"fs";import{join as f}from"path";var y=class{server;client;config;isInitialized=!1;constructor(e){this.config=e||{},this.server=new j({name:"sudocode",version:"0.1.0"},{capabilities:{tools:{},resources:{}}}),this.client=new l(e),this.setupHandlers()}setupHandlers(){this.server.setRequestHandler(H,async()=>({tools:[{name:"ready",description:"Find issues ready to work on (no blockers) and gets project status.",inputSchema:{type:"object",properties:{}}},{name:"list_issues",description:"List all issues with optional filters",inputSchema:{type:"object",properties:{status:{type:"string",enum:["open","in_progress","blocked","closed"],description:"Filter by status (optional)"},priority:{type:"number",description:"Filter by priority (0-4) (optional)"},archived:{type:"boolean",description:"Filter by archived status (optional, defaults to false to exclude archived)"},limit:{type:"number",description:"Max results (optional)",default:50},search:{type:"string",description:"Search issues by title or description (optional)"}}}},{name:"show_issue",description:"Show detailed issue information including relationships and feedback",inputSchema:{type:"object",properties:{issue_id:{type:"string",description:'Issue ID (e.g., "ISSUE-001")'}},required:["issue_id"]}},{name:"upsert_issue",description:"Create or update an issue. If issue_id is provided, updates the issue; otherwise creates a new one. To close an issue, set status='closed'. To archive an issue, set archived=true.",inputSchema:{type:"object",properties:{issue_id:{type:"string",description:"Issue ID (optional - if provided, updates the issue; if not, creates new)"},title:{type:"string",description:"Issue title (required for create, optional for update)"},description:{type:"string",description:"Issue descriptions. Supports inline references to other specs/issues by ID in Obsidian internal link format (e.g. `[[SPEC-002]]`)."},priority:{type:"number",description:"Priority (0-4, 0=highest) (optional)"},parent:{type:"string",description:"Parent issue ID (optional)"},tags:{type:"array",items:{type:"string"},description:"Tags (optional)"},status:{type:"string",enum:["open","in_progress","blocked","closed"],description:"Issue status (optional)"},archived:{type:"boolean",description:"Archive status (optional)"}}}},{name:"list_specs",description:"List all specs with optional filters",inputSchema:{type:"object",properties:{limit:{type:"number",description:"Max results (optional)",default:50},search:{type:"string",description:"Search specs by title or description (optional)"}}}},{name:"show_spec",description:"Show detailed spec information including all feedback anchored to the spec",inputSchema:{type:"object",properties:{spec_id:{type:"string",description:'Spec ID (e.g., "SPEC-001")'}},required:["spec_id"]}},{name:"upsert_spec",description:"Create a new spec (update not yet supported in CLI)",inputSchema:{type:"object",properties:{spec_id:{type:"string",description:"Spec ID (optional - if provided, updates the spec; if not, creates new)"},title:{type:"string",description:"Spec title (required for create)"},priority:{type:"number",description:"Priority (0-4, 0=highest) (optional)"},description:{type:"string",description:"Spec description (optional)"},parent:{type:"string",description:"Parent spec ID (optional)"},tags:{type:"array",items:{type:"string"},description:"Tags (optional)"}}}},{name:"link",description:"Create a relationship between two entities (specs or issues)",inputSchema:{type:"object",properties:{from_id:{type:"string",description:"Source entity ID"},to_id:{type:"string",description:"Target entity ID"},type:{type:"string",enum:["blocks","implements","references","depends-on","discovered-from","related"],description:"Relationship type"}},required:["from_id","to_id"]}},{name:"add_reference",description:"Add an inline cross-reference/mention to a spec or issue using Obsidian-style [[ID]] syntax. References are inserted at a specific location in the markdown content. Use this to add references to an issue or spec without having to modify the content directly.",inputSchema:{type:"object",properties:{entity_id:{type:"string",description:"Target entity ID (where to add the reference)"},reference_id:{type:"string",description:"ID to reference (e.g., ISSUE-001, SPEC-002)"},display_text:{type:"string",description:"Display text (optional)"},relationship_type:{type:"string",enum:["blocks","implements","references","depends-on","discovered-from","related"],description:"Relationship type (optional)"},line:{type:"number",description:"Line number to insert reference (use line OR text, not both)"},text:{type:"string",description:"Text to search for insertion point (use line OR text, not both)"},format:{type:"string",enum:["inline","newline"],description:"Format: inline (same line) or newline (new line)",default:"inline"}},required:["entity_id","reference_id"]}},{name:"add_feedback",description:"Provide anchored feedback to a spec. IMPORTANT: You MUST specify either 'line' OR 'text' to anchor the feedback to a specific location in the spec. ",inputSchema:{type:"object",properties:{issue_id:{type:"string",description:"Issue ID providing feedback (required for create)"},spec_id:{type:"string",description:"Spec ID receiving feedback (required for create)"},content:{type:"string",description:"Feedback content (required for create)"},type:{type:"string",enum:["comment","suggestion","request"],description:"Feedback type"},line:{type:"number",description:"Line number to anchor feedback (REQUIRED: must use either 'line' OR 'text', not both). Use this if you know the exact line number in the spec markdown file."},text:{type:"string",description:"Text snippet to anchor feedback (REQUIRED: must use either 'line' OR 'text', not both). Must be an EXACT substring match from the spec content - case-sensitive and whitespace-sensitive. Use show_spec first to see the exact content and copy the text precisely."}}}}]})),this.server.setRequestHandler($,async e=>{let{name:t,arguments:i}=e.params;if(!this.isInitialized)return{content:[{type:"text",text:`\u26A0\uFE0F sudocode is not initialized in this directory.
3
+
4
+ Working directory: ${this.client.workingDir||process.cwd()}
5
+
6
+ Please run 'sudocode init' in your project root first.`}],isError:!0};try{let s;switch(t){case"ready":s=await S(this.client,i);break;case"list_issues":s=await k(this.client,i);break;case"show_issue":s=await x(this.client,i);break;case"upsert_issue":s=await v(this.client,i);break;case"list_specs":s=await _(this.client,i);break;case"show_spec":s=await I(this.client,i);break;case"upsert_spec":s=await P(this.client,i);break;case"link":s=await C(this.client,i);break;case"add_reference":s=await T(this.client,i);break;case"add_feedback":s=await D(this.client,i);break;default:throw new Error(`Unknown tool: ${t}`)}return{content:[{type:"text",text:JSON.stringify(s,null,2)}]}}catch(s){let n=`Error: ${s instanceof Error?s.message:String(s)}`;return s instanceof Error&&"stderr"in s&&s.stderr&&(n+=`
7
+
8
+ Stderr:
9
+ ${s.stderr}`),{content:[{type:"text",text:n}],isError:!0}}}),this.server.setRequestHandler(N,async()=>({resources:[{uri:"sudocode://quickstart",name:"sudocode Quickstart Guide",description:"Introduction to sudocode workflow and best practices for agents",mimeType:"text/markdown"}]})),this.server.setRequestHandler(M,async e=>{let{uri:t}=e.params;if(t==="sudocode://quickstart")return{contents:[{uri:t,mimeType:"text/markdown",text:`# sudocode Quickstart
10
+
11
+ sudocode is a git-native spec and issue management system designed for AI-assisted development.
12
+
13
+ ## Core Concepts
14
+
15
+ **Specs**: Technical specifications stored as markdown files
16
+ - Types: architecture, api, database, feature, research
17
+ - Status: draft \u2192 review \u2192 approved \u2192 deprecated
18
+ - Each spec has a unique ID (e.g., SPEC-001) and file path
19
+
20
+ **Issues**: Work items tracked in the database
21
+ - Types: bug, feature, task, epic, chore
22
+ - Status: open \u2192 in_progress \u2192 blocked \u2192 closed
23
+ - Can reference and implement specs
24
+
25
+ **Feedback**: Issues can provide anchored feedback on specs
26
+ - Anchors track specific lines/sections in spec markdown
27
+ - Auto-relocates when specs change (smart anchoring)
28
+ - Types: comment, suggestion, request
29
+
30
+ ## Typical Workflow
31
+
32
+ 1. **Check ready work**: \`ready\` tool to find tasks with no blockers
33
+ 2. **Claim work**: \`update_issue\` with status=in_progress
34
+ 3. **Review specs**: \`show_spec\` to understand requirements
35
+ 4. **Provide feedback**: \`add_feedback\` when specs are unclear
36
+ 5. **Complete work**: \`close_issue\` when done
37
+ 6. **Link entities**: Use \`link\` to create relationships
38
+
39
+ ## Relationship Types
40
+ - \`blocks\`: Hard blocker (to_id must complete before from_id)
41
+ - \`implements\`: Issue implements a spec
42
+ - \`references\`: Soft reference
43
+ - \`depends-on\`: General dependency
44
+ - \`discovered-from\`: New work found during implementation
45
+ - \`related\`: General relationship
46
+ `}]};throw new Error(`Unknown resource: ${t}`)})}async checkForInit(){let e=this.client.workingDir||process.cwd(),t=f(e,".sudocode"),i=f(t,"cache.db"),s=f(t,"issues.jsonl"),n=f(t,"specs.jsonl");if(!h(t))return{initialized:!1,sudocodeExists:!1,message:"No .sudocode directory found"};if(!h(i))if(h(s)||h(n))try{return console.error("Found .sudocode directory but no cache.db, running import..."),await this.client.exec(["import"]),console.error("\u2713 Successfully imported data to cache.db"),{initialized:!0,sudocodeExists:!0,message:"Auto-imported from JSONL files"}}catch(o){return{initialized:!1,sudocodeExists:!0,message:`Failed to import: ${o instanceof Error?o.message:String(o)}`}}else try{return console.error("Found .sudocode directory but no issues.jsonl or specs.jsonl, running init..."),await this.client.exec(["init"]),console.error("\u2713 Successfully initialized sudocode"),await this.client.exec(["import"]),{initialized:!0,sudocodeExists:!0,message:"Initialized sudocode"}}catch(o){return{initialized:!1,sudocodeExists:!0,message:`Failed to initialize: ${o instanceof Error?o.message:String(o)}`}}return{initialized:!0,sudocodeExists:!0}}async checkInitialization(){let e=await this.checkForInit(),t=this.client.workingDir||process.cwd();e.initialized?(this.isInitialized=!0,console.error("\u2713 sudocode initialized successfully"),e.message&&console.error(` ${e.message}`)):(this.isInitialized=!1,console.error(""),console.error("\u26A0\uFE0F WARNING: sudocode is not initialized"),console.error(` Working directory: ${t}`),console.error(""),e.sudocodeExists?(console.error(` Issue: ${e.message}`),console.error(" The .sudocode directory exists but is incomplete."),console.error(" Try running:"),console.error(" $ sudocode import")):(console.error(" No .sudocode directory found."),console.error(" To initialize, run:"),console.error(" $ sudocode init")))}async run(){await this.checkInitialization();let e=new z;await this.server.connect(e),console.error("sudocode MCP server running on stdio")}};function W(){let r={},e=process.argv.slice(2);for(let t=0;t<e.length;t++){let i=e[t];switch(i){case"--working-dir":case"-w":r.workingDir=e[++t];break;case"--cli-path":r.cliPath=e[++t];break;case"--db-path":case"--db":r.dbPath=e[++t];break;case"--no-sync":r.syncOnStartup=!1;break;case"--help":case"-h":console.log(`
47
+ sudocode MCP Server
48
+
49
+ Usage: sudocode-mcp [options]
50
+
51
+ Options:
52
+ -w, --working-dir <path> Working directory (default: cwd or SUDOCODE_WORKING_DIR)
53
+ --cli-path <path> Path to sudocode CLI (default: 'sudocode' or SUDOCODE_PATH)
54
+ --db-path <path> Database path (default: auto-discover or SUDOCODE_DB)
55
+ --no-sync Skip initial sync on startup (default: sync enabled)
56
+ -h, --help Show this help message
57
+
58
+ Environment Variables:
59
+ SUDOCODE_WORKING_DIR Default working directory
60
+ SUDOCODE_PATH Default CLI path
61
+ SUDOCODE_DB Default database path
62
+ `),process.exit(0);break;default:console.error(`Unknown option: ${i}`),console.error("Use --help for usage information"),process.exit(1)}}return r}async function G(){let r=W();await new y(r).run()}G().catch(r=>{console.error("Fatal error:",r),process.exit(1)});
63
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/server.ts", "../src/client.ts", "../src/types.ts", "../src/tools/issues.ts", "../src/tools/specs.ts", "../src/tools/relationships.ts", "../src/tools/feedback.ts", "../src/tools/references.ts", "../src/index.ts"],
4
+ "sourcesContent": ["/**\n * MCP Server for sudocode\n *\n * This module sets up the MCP server with tools and resources.\n */\n\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ListResourcesRequestSchema,\n ListToolsRequestSchema,\n ReadResourceRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { SudocodeClient } from \"./client.js\";\nimport * as issueTools from \"./tools/issues.js\";\nimport * as specTools from \"./tools/specs.js\";\nimport * as relationshipTools from \"./tools/relationships.js\";\nimport * as feedbackTools from \"./tools/feedback.js\";\nimport * as referenceTools from \"./tools/references.js\";\nimport { SudocodeClientConfig } from \"./types.js\";\nimport { existsSync } from \"fs\";\nimport { join } from \"path\";\n\nexport class SudocodeMCPServer {\n private server: Server;\n private client: SudocodeClient;\n private config: SudocodeClientConfig;\n private isInitialized: boolean = false;\n\n constructor(config?: SudocodeClientConfig) {\n this.config = config || {};\n this.server = new Server(\n {\n name: \"sudocode\",\n version: \"0.1.0\",\n },\n {\n capabilities: {\n tools: {},\n resources: {},\n },\n }\n );\n\n this.client = new SudocodeClient(config);\n this.setupHandlers();\n }\n\n private setupHandlers() {\n // List available tools\n this.server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: [\n {\n name: \"ready\",\n description:\n \"Find issues ready to work on (no blockers) and gets project status.\",\n inputSchema: {\n type: \"object\",\n properties: {},\n },\n },\n {\n name: \"list_issues\",\n description: \"List all issues with optional filters\",\n inputSchema: {\n type: \"object\",\n properties: {\n status: {\n type: \"string\",\n enum: [\"open\", \"in_progress\", \"blocked\", \"closed\"],\n description: \"Filter by status (optional)\",\n },\n priority: {\n type: \"number\",\n description: \"Filter by priority (0-4) (optional)\",\n },\n archived: {\n type: \"boolean\",\n description:\n \"Filter by archived status (optional, defaults to false to exclude archived)\",\n },\n limit: {\n type: \"number\",\n description: \"Max results (optional)\",\n default: 50,\n },\n search: {\n type: \"string\",\n description:\n \"Search issues by title or description (optional)\",\n },\n },\n },\n },\n {\n name: \"show_issue\",\n description:\n \"Show detailed issue information including relationships and feedback\",\n inputSchema: {\n type: \"object\",\n properties: {\n issue_id: {\n type: \"string\",\n description: 'Issue ID (e.g., \"ISSUE-001\")',\n },\n },\n required: [\"issue_id\"],\n },\n },\n {\n name: \"upsert_issue\",\n description:\n \"Create or update an issue. If issue_id is provided, updates the issue; otherwise creates a new one. To close an issue, set status='closed'. To archive an issue, set archived=true.\",\n inputSchema: {\n type: \"object\",\n properties: {\n issue_id: {\n type: \"string\",\n description:\n \"Issue ID (optional - if provided, updates the issue; if not, creates new)\",\n },\n title: {\n type: \"string\",\n description:\n \"Issue title (required for create, optional for update)\",\n },\n description: {\n type: \"string\",\n description:\n \"Issue descriptions. Supports inline references to other specs/issues by ID in Obsidian internal link format (e.g. `[[SPEC-002]]`).\",\n },\n priority: {\n type: \"number\",\n description: \"Priority (0-4, 0=highest) (optional)\",\n },\n parent: {\n type: \"string\",\n description: \"Parent issue ID (optional)\",\n },\n tags: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Tags (optional)\",\n },\n status: {\n type: \"string\",\n enum: [\"open\", \"in_progress\", \"blocked\", \"closed\"],\n description: \"Issue status (optional)\",\n },\n archived: {\n type: \"boolean\",\n description: \"Archive status (optional)\",\n },\n },\n },\n },\n {\n name: \"list_specs\",\n description: \"List all specs with optional filters\",\n inputSchema: {\n type: \"object\",\n properties: {\n limit: {\n type: \"number\",\n description: \"Max results (optional)\",\n default: 50,\n },\n search: {\n type: \"string\",\n description:\n \"Search specs by title or description (optional)\",\n },\n },\n },\n },\n {\n name: \"show_spec\",\n description:\n \"Show detailed spec information including all feedback anchored to the spec\",\n inputSchema: {\n type: \"object\",\n properties: {\n spec_id: {\n type: \"string\",\n description: 'Spec ID (e.g., \"SPEC-001\")',\n },\n },\n required: [\"spec_id\"],\n },\n },\n {\n name: \"upsert_spec\",\n description: \"Create a new spec (update not yet supported in CLI)\",\n inputSchema: {\n type: \"object\",\n properties: {\n spec_id: {\n type: \"string\",\n description:\n \"Spec ID (optional - if provided, updates the spec; if not, creates new)\",\n },\n title: {\n type: \"string\",\n description: \"Spec title (required for create)\",\n },\n priority: {\n type: \"number\",\n description: \"Priority (0-4, 0=highest) (optional)\",\n },\n description: {\n type: \"string\",\n description: \"Spec description (optional)\",\n },\n parent: {\n type: \"string\",\n description: \"Parent spec ID (optional)\",\n },\n tags: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Tags (optional)\",\n },\n },\n },\n },\n {\n name: \"link\",\n description:\n \"Create a relationship between two entities (specs or issues)\",\n inputSchema: {\n type: \"object\",\n properties: {\n from_id: {\n type: \"string\",\n description: \"Source entity ID\",\n },\n to_id: {\n type: \"string\",\n description: \"Target entity ID\",\n },\n type: {\n type: \"string\",\n enum: [\n \"blocks\",\n \"implements\",\n \"references\",\n \"depends-on\",\n \"discovered-from\",\n \"related\",\n ],\n description: \"Relationship type\",\n },\n },\n required: [\"from_id\", \"to_id\"],\n },\n },\n {\n name: \"add_reference\",\n description:\n \"Add an inline cross-reference/mention to a spec or issue using Obsidian-style [[ID]] syntax. References are inserted at a specific location in the markdown content. Use this to add references to an issue or spec without having to modify the content directly.\",\n inputSchema: {\n type: \"object\",\n properties: {\n entity_id: {\n type: \"string\",\n description: \"Target entity ID (where to add the reference)\",\n },\n reference_id: {\n type: \"string\",\n description: \"ID to reference (e.g., ISSUE-001, SPEC-002)\",\n },\n display_text: {\n type: \"string\",\n description: \"Display text (optional)\",\n },\n relationship_type: {\n type: \"string\",\n enum: [\n \"blocks\",\n \"implements\",\n \"references\",\n \"depends-on\",\n \"discovered-from\",\n \"related\",\n ],\n description: \"Relationship type (optional)\",\n },\n line: {\n type: \"number\",\n description:\n \"Line number to insert reference (use line OR text, not both)\",\n },\n text: {\n type: \"string\",\n description:\n \"Text to search for insertion point (use line OR text, not both)\",\n },\n format: {\n type: \"string\",\n enum: [\"inline\", \"newline\"],\n description:\n \"Format: inline (same line) or newline (new line)\",\n default: \"inline\",\n },\n // TODO: Add position handling later if needed.\n },\n required: [\"entity_id\", \"reference_id\"],\n },\n },\n {\n name: \"add_feedback\",\n description:\n \"Provide anchored feedback to a spec. IMPORTANT: You MUST specify either 'line' OR 'text' to anchor the feedback to a specific location in the spec. \",\n inputSchema: {\n type: \"object\",\n properties: {\n issue_id: {\n type: \"string\",\n description:\n \"Issue ID providing feedback (required for create)\",\n },\n spec_id: {\n type: \"string\",\n description:\n \"Spec ID receiving feedback (required for create)\",\n },\n content: {\n type: \"string\",\n description: \"Feedback content (required for create)\",\n },\n type: {\n type: \"string\",\n enum: [\"comment\", \"suggestion\", \"request\"],\n description: \"Feedback type\",\n },\n line: {\n type: \"number\",\n description:\n \"Line number to anchor feedback (REQUIRED: must use either 'line' OR 'text', not both). Use this if you know the exact line number in the spec markdown file.\",\n },\n text: {\n type: \"string\",\n description:\n \"Text snippet to anchor feedback (REQUIRED: must use either 'line' OR 'text', not both). Must be an EXACT substring match from the spec content - case-sensitive and whitespace-sensitive. Use show_spec first to see the exact content and copy the text precisely.\",\n },\n // TODO: Re-enable when the agent data structure is more developed.\n // agent: {\n // type: \"string\",\n // description: \"Agent providing feedback\",\n // },\n },\n },\n },\n ],\n };\n });\n\n // Handle tool calls\n this.server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n if (!this.isInitialized) {\n const workingDir = this.client[\"workingDir\"] || process.cwd();\n return {\n content: [\n {\n type: \"text\",\n text: `\u26A0\uFE0F sudocode is not initialized in this directory.\\n\\nWorking directory: ${workingDir}\\n\\nPlease run 'sudocode init' in your project root first.`,\n },\n ],\n isError: true,\n };\n }\n\n try {\n let result: any;\n\n switch (name) {\n case \"ready\":\n result = await issueTools.ready(this.client, args as any);\n break;\n\n case \"list_issues\":\n result = await issueTools.listIssues(this.client, args as any);\n break;\n\n case \"show_issue\":\n result = await issueTools.showIssue(this.client, args as any);\n break;\n\n case \"upsert_issue\":\n result = await issueTools.upsertIssue(this.client, args as any);\n break;\n\n case \"list_specs\":\n result = await specTools.listSpecs(this.client, args as any);\n break;\n\n case \"show_spec\":\n result = await specTools.showSpec(this.client, args as any);\n break;\n\n case \"upsert_spec\":\n result = await specTools.upsertSpec(this.client, args as any);\n break;\n\n case \"link\":\n result = await relationshipTools.link(this.client, args as any);\n break;\n\n case \"add_reference\":\n result = await referenceTools.addReference(\n this.client,\n args as any\n );\n break;\n\n case \"add_feedback\":\n result = await feedbackTools.addFeedback(this.client, args as any);\n break;\n\n default:\n throw new Error(`Unknown tool: ${name}`);\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n } catch (error) {\n let errorText = `Error: ${\n error instanceof Error ? error.message : String(error)\n }`;\n\n // Include stderr if this is a sudocode error\n if (error instanceof Error && \"stderr\" in error && error.stderr) {\n errorText += `\\n\\nStderr:\\n${error.stderr}`;\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: errorText,\n },\n ],\n isError: true,\n };\n }\n });\n\n // List available resources\n this.server.setRequestHandler(ListResourcesRequestSchema, async () => {\n return {\n resources: [\n {\n uri: \"sudocode://quickstart\",\n name: \"sudocode Quickstart Guide\",\n description:\n \"Introduction to sudocode workflow and best practices for agents\",\n mimeType: \"text/markdown\",\n },\n ],\n };\n });\n\n // Read resource content\n this.server.setRequestHandler(\n ReadResourceRequestSchema,\n async (request) => {\n const { uri } = request.params;\n\n if (uri === \"sudocode://quickstart\") {\n return {\n contents: [\n {\n uri,\n mimeType: \"text/markdown\",\n text: `# sudocode Quickstart\n\nsudocode is a git-native spec and issue management system designed for AI-assisted development.\n\n## Core Concepts\n\n**Specs**: Technical specifications stored as markdown files\n- Types: architecture, api, database, feature, research\n- Status: draft \u2192 review \u2192 approved \u2192 deprecated\n- Each spec has a unique ID (e.g., SPEC-001) and file path\n\n**Issues**: Work items tracked in the database\n- Types: bug, feature, task, epic, chore\n- Status: open \u2192 in_progress \u2192 blocked \u2192 closed\n- Can reference and implement specs\n\n**Feedback**: Issues can provide anchored feedback on specs\n- Anchors track specific lines/sections in spec markdown\n- Auto-relocates when specs change (smart anchoring)\n- Types: comment, suggestion, request\n\n## Typical Workflow\n\n1. **Check ready work**: \\`ready\\` tool to find tasks with no blockers\n2. **Claim work**: \\`update_issue\\` with status=in_progress\n3. **Review specs**: \\`show_spec\\` to understand requirements\n4. **Provide feedback**: \\`add_feedback\\` when specs are unclear\n5. **Complete work**: \\`close_issue\\` when done\n6. **Link entities**: Use \\`link\\` to create relationships\n\n## Relationship Types\n- \\`blocks\\`: Hard blocker (to_id must complete before from_id)\n- \\`implements\\`: Issue implements a spec\n- \\`references\\`: Soft reference\n- \\`depends-on\\`: General dependency\n- \\`discovered-from\\`: New work found during implementation\n- \\`related\\`: General relationship\n`,\n },\n ],\n };\n }\n\n throw new Error(`Unknown resource: ${uri}`);\n }\n );\n }\n\n /**\n * Check for .sudocode directory and required files\n * Returns initialization status and handles auto-import if needed\n */\n private async checkForInit(): Promise<{\n initialized: boolean;\n sudocodeExists: boolean;\n message?: string;\n }> {\n const workingDir = this.client[\"workingDir\"] || process.cwd();\n const sudocodeDir = join(workingDir, \".sudocode\");\n const cacheDbPath = join(sudocodeDir, \"cache.db\");\n const issuesPath = join(sudocodeDir, \"issues.jsonl\");\n const specsPath = join(sudocodeDir, \"specs.jsonl\");\n\n // Check if .sudocode directory exists\n if (!existsSync(sudocodeDir)) {\n return {\n initialized: false,\n sudocodeExists: false,\n message: \"No .sudocode directory found\",\n };\n }\n\n // .sudocode exists, check for cache.db\n if (!existsSync(cacheDbPath)) {\n // Try to auto-import from JSONL files if they exist\n if (existsSync(issuesPath) || existsSync(specsPath)) {\n try {\n console.error(\n \"Found .sudocode directory but no cache.db, running import...\"\n );\n await this.client.exec([\"import\"]);\n console.error(\"\u2713 Successfully imported data to cache.db\");\n return {\n initialized: true,\n sudocodeExists: true,\n message: \"Auto-imported from JSONL files\",\n };\n } catch (error) {\n return {\n initialized: false,\n sudocodeExists: true,\n message: `Failed to import: ${\n error instanceof Error ? error.message : String(error)\n }`,\n };\n }\n } else {\n try {\n console.error(\n \"Found .sudocode directory but no issues.jsonl or specs.jsonl, running init...\"\n );\n await this.client.exec([\"init\"]);\n console.error(\"\u2713 Successfully initialized sudocode\");\n await this.client.exec([\"import\"]);\n return {\n initialized: true,\n sudocodeExists: true,\n message: \"Initialized sudocode\",\n };\n } catch (error) {\n return {\n initialized: false,\n sudocodeExists: true,\n message: `Failed to initialize: ${\n error instanceof Error ? error.message : String(error)\n }`,\n };\n }\n }\n }\n\n return {\n initialized: true,\n sudocodeExists: true,\n };\n }\n\n /**\n * Check if sudocode is initialized in the working directory\n * This provides early warning to users without blocking server startup\n */\n private async checkInitialization() {\n const initStatus = await this.checkForInit();\n const workingDir = this.client[\"workingDir\"] || process.cwd();\n\n if (initStatus.initialized) {\n this.isInitialized = true;\n console.error(\"\u2713 sudocode initialized successfully\");\n if (initStatus.message) {\n console.error(` ${initStatus.message}`);\n }\n } else {\n this.isInitialized = false;\n console.error(\"\");\n console.error(\"\u26A0\uFE0F WARNING: sudocode is not initialized\");\n console.error(` Working directory: ${workingDir}`);\n console.error(\"\");\n\n if (!initStatus.sudocodeExists) {\n console.error(\" No .sudocode directory found.\");\n console.error(\" To initialize, run:\");\n console.error(\" $ sudocode init\");\n } else {\n console.error(` Issue: ${initStatus.message}`);\n console.error(\" The .sudocode directory exists but is incomplete.\");\n console.error(\" Try running:\");\n console.error(\" $ sudocode import\");\n }\n }\n }\n\n async run() {\n // Check if sudocode is initialized (non-blocking warning)\n await this.checkInitialization();\n\n const transport = new StdioServerTransport();\n await this.server.connect(transport);\n console.error(\"sudocode MCP server running on stdio\");\n }\n}\n", "/**\n * sudocode CLI client wrapper\n *\n * This module provides a client class that spawns `sudocode` CLI commands\n * and parses their JSON output for use in MCP tools.\n */\n\nimport { spawn } from \"child_process\";\nimport { fileURLToPath } from \"url\";\nimport { dirname, join } from \"path\";\nimport { existsSync, writeFileSync, chmodSync } from \"fs\";\nimport { SudocodeClientConfig, SudocodeError } from \"./types.js\";\n\nexport class SudocodeClient {\n private workingDir: string;\n private cliPath: string;\n private cliArgs: string[];\n private dbPath?: string;\n private versionChecked = false;\n\n constructor(config?: SudocodeClientConfig) {\n // Get working directory and expand variables if needed\n let workingDir =\n config?.workingDir || process.env.SUDOCODE_WORKING_DIR || process.cwd();\n\n // Fix unexpanded ${workspaceFolder} variable - use PWD or cwd() instead\n if (workingDir === \"${workspaceFolder}\" || workingDir.includes(\"${\")) {\n workingDir = process.env.PWD || process.cwd();\n }\n\n this.workingDir = workingDir;\n this.dbPath = config?.dbPath || process.env.SUDOCODE_DB;\n\n // Auto-discover CLI path from node_modules or use configured/env path\n const cliInfo = this.findCliPath();\n this.cliPath = cliInfo.path;\n this.cliArgs = cliInfo.args;\n }\n\n /**\n * Find the CLI by looking in node_modules/@sudocode-ai/cli\n * Since we added @sudocode-ai/cli as a dependency, it should be there\n */\n private findCliPath(): { path: string; args: string[] } {\n try {\n const currentFile = fileURLToPath(import.meta.url);\n const currentDir = dirname(currentFile);\n\n // Look for @sudocode-ai/cli in various possible locations\n const possiblePaths = [\n // Workspace root node_modules (development)\n join(\n currentDir,\n \"..\",\n \"..\",\n \"node_modules\",\n \"@sudocode-ai\",\n \"cli\",\n \"dist\",\n \"cli.js\"\n ),\n // Local package node_modules (when installed from npm)\n join(\n currentDir,\n \"..\",\n \"node_modules\",\n \"@sudocode-ai\",\n \"cli\",\n \"dist\",\n \"cli.js\"\n ),\n ];\n\n for (const cliJsPath of possiblePaths) {\n if (existsSync(cliJsPath)) {\n // Return node + cli.js path instead of creating a wrapper\n return {\n path: process.execPath, // Use current node binary\n args: [cliJsPath], // Pass cli.js as first argument\n };\n }\n }\n } catch (error) {\n // Ignore errors and fall back to 'sudocode' command\n }\n\n // Fall back to 'sudocode' command in PATH\n return { path: \"sudocode\", args: [] };\n }\n\n /**\n * Execute a CLI command and return parsed JSON output\n */\n async exec(args: string[], options?: { timeout?: number }): Promise<any> {\n // Check CLI version on first call\n if (!this.versionChecked) {\n await this.checkVersion();\n this.versionChecked = true;\n }\n\n // Build command arguments - prepend cliArgs (e.g., cli.js path)\n const cmdArgs = [...this.cliArgs, ...args];\n\n // Add --json flag if not already present\n if (!cmdArgs.includes(\"--json\")) {\n cmdArgs.push(\"--json\");\n }\n\n // Add --db flag if dbPath is configured\n if (this.dbPath && !cmdArgs.includes(\"--db\")) {\n cmdArgs.push(\"--db\", this.dbPath);\n }\n\n return new Promise((resolve, reject) => {\n const proc = spawn(this.cliPath, cmdArgs, {\n cwd: this.workingDir,\n env: process.env,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n proc.stdout.on(\"data\", (data) => {\n stdout += data.toString();\n });\n\n proc.stderr.on(\"data\", (data) => {\n stderr += data.toString();\n });\n\n // Set timeout if specified\n const timeout = options?.timeout || 30000; // Default 30s\n const timer = setTimeout(() => {\n proc.kill();\n reject(\n new SudocodeError(\n `Command timed out after ${timeout}ms`,\n -1,\n \"Timeout\"\n )\n );\n }, timeout);\n\n proc.on(\"close\", (code) => {\n clearTimeout(timer);\n\n if (code !== 0) {\n reject(\n new SudocodeError(\n `CLI command failed with exit code ${code}`,\n code || -1,\n stderr\n )\n );\n return;\n }\n\n // Parse JSON output\n try {\n const result = JSON.parse(stdout);\n resolve(result);\n } catch (error) {\n reject(\n new SudocodeError(\n `Failed to parse JSON output: ${\n error instanceof Error ? error.message : String(error)\n }`,\n -1,\n stdout\n )\n );\n }\n });\n\n proc.on(\"error\", (error) => {\n clearTimeout(timer);\n reject(\n new SudocodeError(\n `Failed to spawn CLI: ${error.message}`,\n -1,\n error.message\n )\n );\n });\n });\n }\n\n /**\n * Check that the CLI is installed and get its version\n */\n async checkVersion(): Promise<{ version: string }> {\n try {\n const proc = spawn(this.cliPath, [...this.cliArgs, \"--version\"], {\n cwd: this.workingDir,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n proc.stdout.on(\"data\", (data) => {\n stdout += data.toString();\n });\n\n proc.stderr.on(\"data\", (data) => {\n stderr += data.toString();\n });\n\n return new Promise((resolve, reject) => {\n proc.on(\"close\", (code) => {\n if (code !== 0) {\n reject(\n new SudocodeError(\n `CLI not found or failed to execute. Make sure 'sudocode' is installed and in your PATH.`,\n code || -1,\n stderr\n )\n );\n return;\n }\n\n // Version output format: \"sudocode version X.Y.Z\" or just \"X.Y.Z\"\n const versionMatch = stdout.match(/(\\d+\\.\\d+\\.\\d+)/);\n const version = versionMatch ? versionMatch[1] : stdout.trim();\n\n resolve({ version });\n });\n\n proc.on(\"error\", () => {\n reject(\n new SudocodeError(\n `CLI not found at path: ${this.cliPath}. Make sure 'sudocode' is installed.`,\n -1,\n \"CLI not found\"\n )\n );\n });\n });\n } catch (error) {\n throw new SudocodeError(\n `Failed to check CLI version: ${\n error instanceof Error ? error.message : String(error)\n }`,\n -1,\n \"\"\n );\n }\n }\n}\n", "/**\n * Type definitions for sudocode MCP server\n *\n * Core entity types are imported from the main sudocode package.\n * This file contains MCP-specific types and some forward-compatible types\n * for fields that may be added to the core package in the future.\n */\n\n// Re-export core types from the main package\nexport type {\n Spec,\n Issue,\n Relationship,\n EntityType,\n RelationshipType,\n IssueStatus,\n FeedbackAnchor,\n FeedbackType,\n IssueFeedback as Feedback,\n} from \"@sudocode-ai/types\";\n\n// ============================================================================\n// MCP-SPECIFIC TYPES\n// These types are used by the MCP interface but may not be fully supported\n// by the current CLI implementation. They represent forward-compatible\n// features that may be added in the future.\n// ============================================================================\n\n/**\n * Issue type classification\n * NOTE: Not yet stored in database or supported by CLI filtering\n */\nexport type IssueType = \"bug\" | \"feature\" | \"task\" | \"epic\" | \"chore\";\n\n/**\n * Spec status lifecycle\n * NOTE: Not yet stored in database or supported by CLI filtering\n */\nexport type SpecStatus = \"draft\" | \"review\" | \"approved\" | \"deprecated\";\n\n/**\n * Spec type classification\n * NOTE: Not yet stored in database or supported by CLI filtering\n */\nexport type SpecType =\n | \"architecture\"\n | \"api\"\n | \"database\"\n | \"feature\"\n | \"research\";\n\n// ============================================================================\n// CLIENT CONFIGURATION\n// ============================================================================\n\nexport interface SudocodeClientConfig {\n workingDir?: string;\n cliPath?: string;\n dbPath?: string;\n syncOnStartup?: boolean;\n}\n\n// ============================================================================\n// ERROR TYPES\n// ============================================================================\n\nexport class SudocodeError extends Error {\n constructor(\n message: string,\n public exitCode: number,\n public stderr: string\n ) {\n super(message);\n this.name = \"SudocodeError\";\n }\n}\n", "/**\n * MCP tools for issue management\n */\n\nimport { SudocodeClient } from \"../client.js\";\nimport { Issue, IssueStatus } from \"../types.js\";\n\n// Tool parameter types\nexport interface ReadyParams {}\n\nexport interface ListIssuesParams {\n status?: IssueStatus;\n priority?: number;\n limit?: number;\n search?: string;\n archived?: boolean;\n}\n\nexport interface ShowIssueParams {\n issue_id: string;\n}\n\nexport interface UpsertIssueParams {\n issue_id?: string; // If provided, update; otherwise create\n title?: string; // Required for create, optional for update\n description?: string;\n priority?: number;\n parent?: string;\n tags?: string[];\n status?: IssueStatus;\n archived?: boolean;\n // TODO: Reintroduce assignee later on when first-class agents are supported.\n}\n\n// Tool implementations\n\n/**\n * Find issues ready to work on (no blockers) and get project status\n */\nexport async function ready(\n client: SudocodeClient,\n params: ReadyParams = {}\n): Promise<any> {\n const readyResult = await client.exec([\"ready\"]);\n const statusResult = await client.exec([\"status\"]);\n\n // Redact content field from issues to keep response shorter\n if (readyResult.issues && Array.isArray(readyResult.issues)) {\n readyResult.issues = readyResult.issues.map((issue: any) => {\n const { content, ...rest } = issue;\n return rest;\n });\n }\n\n return {\n ready: readyResult,\n status: statusResult,\n };\n}\n\n/**\n * List all issues with optional filters\n */\nexport async function listIssues(\n client: SudocodeClient,\n params: ListIssuesParams = {}\n): Promise<Issue[]> {\n const args = [\"issue\", \"list\"];\n\n if (params.status) {\n args.push(\"--status\", params.status);\n }\n if (params.priority !== undefined) {\n args.push(\"--priority\", params.priority.toString());\n }\n if (params.limit !== undefined) {\n args.push(\"--limit\", params.limit.toString());\n }\n if (params.search) {\n args.push(\"--grep\", params.search);\n }\n // Default to excluding archived unless explicitly specified\n const archived = params.archived !== undefined ? params.archived : false;\n args.push(\"--archived\", archived.toString());\n\n const issues = await client.exec(args);\n\n // Redact content field from issues to keep response shorter\n if (Array.isArray(issues)) {\n return issues.map((issue: any) => {\n const { content, ...rest } = issue;\n return rest;\n });\n }\n\n return issues;\n}\n\n/**\n * Show detailed issue information including relationships and feedback\n */\nexport async function showIssue(\n client: SudocodeClient,\n params: ShowIssueParams\n): Promise<any> {\n const args = [\"issue\", \"show\", params.issue_id];\n return client.exec(args);\n}\n\n/**\n * Upsert an issue (create if no issue_id, update if issue_id provided)\n */\nexport async function upsertIssue(\n client: SudocodeClient,\n params: UpsertIssueParams\n): Promise<Issue> {\n const isUpdate = !!params.issue_id;\n\n if (isUpdate) {\n // Update mode\n const args = [\"issue\", \"update\", params.issue_id!];\n\n if (params.status) {\n args.push(\"--status\", params.status);\n }\n if (params.priority !== undefined) {\n args.push(\"--priority\", params.priority.toString());\n }\n if (params.title) {\n args.push(\"--title\", params.title);\n }\n if (params.description) {\n args.push(\"--description\", params.description);\n }\n if (params.archived !== undefined) {\n args.push(\"--archived\", params.archived.toString());\n }\n\n return client.exec(args);\n } else {\n // Create mode\n if (!params.title) {\n throw new Error(\"title is required when creating a new issue\");\n }\n\n const args = [\"issue\", \"create\", params.title];\n\n if (params.description) {\n args.push(\"--description\", params.description);\n }\n if (params.priority !== undefined) {\n args.push(\"--priority\", params.priority.toString());\n }\n if (params.parent) {\n args.push(\"--parent\", params.parent);\n }\n if (params.tags && params.tags.length > 0) {\n args.push(\"--tags\", params.tags.join(\",\"));\n }\n\n return client.exec(args);\n }\n}\n", "/**\n * MCP tools for spec management\n */\n\nimport { SudocodeClient } from \"../client.js\";\nimport { Spec } from \"../types.js\";\n\n// Tool parameter types\nexport interface ListSpecsParams {\n limit?: number;\n search?: string;\n archived?: boolean;\n}\n\nexport interface ShowSpecParams {\n spec_id: string;\n}\n\nexport interface UpsertSpecParams {\n spec_id?: string; // If provided, update; otherwise create\n title?: string; // Required for create, optional for update\n priority?: number;\n description?: string;\n parent?: string;\n tags?: string[];\n archived?: boolean;\n}\n\n// Tool implementations\n\n/**\n * List all specs with optional filters\n */\nexport async function listSpecs(\n client: SudocodeClient,\n params: ListSpecsParams = {}\n): Promise<Spec[]> {\n const args = [\"spec\", \"list\"];\n\n if (params.limit !== undefined) {\n args.push(\"--limit\", params.limit.toString());\n }\n if (params.search) {\n args.push(\"--grep\", params.search);\n }\n // Default to excluding archived unless explicitly specified\n const archived = params.archived !== undefined ? params.archived : false;\n args.push(\"--archived\", archived.toString());\n\n const specs = await client.exec(args);\n\n // Redact content field from specs to keep response shorter\n if (Array.isArray(specs)) {\n return specs.map((spec: any) => {\n const { content, ...rest } = spec;\n return rest;\n });\n }\n\n return specs;\n}\n\n/**\n * Show detailed spec information including feedback\n */\nexport async function showSpec(\n client: SudocodeClient,\n params: ShowSpecParams\n): Promise<any> {\n const args = [\"spec\", \"show\", params.spec_id];\n return client.exec(args);\n}\n\n/**\n * Upsert a spec (create if no spec_id, update if spec_id provided)\n */\nexport async function upsertSpec(\n client: SudocodeClient,\n params: UpsertSpecParams\n): Promise<Spec> {\n const isUpdate = !!params.spec_id;\n\n if (isUpdate) {\n // Update mode\n const args = [\"spec\", \"update\", params.spec_id!];\n\n if (params.title) {\n args.push(\"--title\", params.title);\n }\n if (params.priority !== undefined) {\n args.push(\"--priority\", params.priority.toString());\n }\n if (params.description) {\n args.push(\"--description\", params.description);\n }\n if (params.parent !== undefined) {\n args.push(\"--parent\", params.parent || \"\");\n }\n if (params.tags !== undefined) {\n args.push(\"--tags\", params.tags.join(\",\"));\n }\n if (params.archived !== undefined) {\n args.push(\"--archived\", params.archived.toString());\n }\n\n return client.exec(args);\n } else {\n // Create mode\n if (!params.title) {\n throw new Error(\"title is required when creating a new spec\");\n }\n\n const args = [\"spec\", \"create\", params.title];\n\n if (params.priority !== undefined) {\n args.push(\"--priority\", params.priority.toString());\n }\n if (params.description) {\n args.push(\"--description\", params.description);\n }\n if (params.parent) {\n args.push(\"--parent\", params.parent);\n }\n if (params.tags && params.tags.length > 0) {\n args.push(\"--tags\", params.tags.join(\",\"));\n }\n\n return client.exec(args);\n }\n}\n", "/**\n * MCP tools for relationship management\n */\n\nimport { SudocodeClient } from \"../client.js\";\n\n// Tool parameter types\nexport type RelationshipType =\n | \"blocks\"\n | \"implements\"\n | \"references\"\n | \"depends-on\"\n | \"discovered-from\"\n | \"related\";\n\nexport interface LinkParams {\n from_id: string;\n to_id: string;\n type?: RelationshipType;\n}\n\n// Tool implementation\n\n/**\n * Create a relationship between two entities (specs or issues)\n */\nexport async function link(\n client: SudocodeClient,\n params: LinkParams\n): Promise<any> {\n const args = [\"link\", params.from_id, params.to_id];\n\n if (params.from_id === params.to_id) {\n throw new Error(\"from_id and to_id cannot be the same\");\n }\n if (params.type) {\n args.push(\"--type\", params.type);\n }\n\n return client.exec(args);\n}\n", "/**\n * MCP tools for feedback management\n */\n\nimport { SudocodeClient } from \"../client.js\";\nimport { Feedback, FeedbackType } from \"../types.js\";\n\n// Tool parameter types\nexport interface AddFeedbackParams {\n issue_id: string;\n spec_id: string;\n content: string;\n type?: FeedbackType;\n line?: number;\n text?: string;\n agent?: string;\n}\n\n/**\n * Add anchored feedback to a spec\n */\nexport async function addFeedback(\n client: SudocodeClient,\n params: AddFeedbackParams\n): Promise<Feedback> {\n const args = [\"feedback\", \"add\", params.issue_id, params.spec_id];\n\n args.push(\"--content\", params.content);\n\n if (params.type) {\n args.push(\"--type\", params.type);\n }\n if (params.line !== undefined) {\n args.push(\"--line\", params.line.toString());\n }\n if (params.text) {\n args.push(\"--text\", params.text);\n }\n // if (params.agent) {\n // args.push(\"--agent\", params.agent);\n // }\n\n return client.exec(args);\n}\n", "/**\n * MCP tools for reference management\n */\n\nimport { SudocodeClient } from \"../client.js\";\n\n// Tool parameter types\nexport interface AddReferenceParams {\n entity_id: string;\n reference_id: string;\n display_text?: string;\n relationship_type?: string;\n line?: number;\n text?: string;\n format?: \"inline\" | \"newline\";\n position?: \"before\" | \"after\";\n}\n\n/**\n * Add a cross-reference to a spec or issue\n *\n * Tries spec first, then issue. The CLI command handles entity validation.\n */\nexport async function addReference(\n client: SudocodeClient,\n params: AddReferenceParams\n): Promise<any> {\n // Build command args\n const buildArgs = (command: \"spec\" | \"issue\") => {\n const args = [command, \"add-ref\", params.entity_id, params.reference_id];\n\n if (params.line !== undefined) {\n args.push(\"--line\", params.line.toString());\n }\n if (params.text) {\n args.push(\"--text\", params.text);\n }\n if (params.display_text) {\n args.push(\"--display\", params.display_text);\n }\n if (params.relationship_type) {\n args.push(\"--type\", params.relationship_type);\n }\n if (params.format) {\n args.push(\"--format\", params.format);\n }\n if (params.position) {\n args.push(\"--position\", params.position);\n }\n\n return args;\n };\n\n // TODO: Infer entity type from ID pattern if possible.\n // Try spec first\n try {\n return await client.exec(buildArgs(\"spec\"));\n } catch (specError) {\n // If spec command fails, try issue\n try {\n return await client.exec(buildArgs(\"issue\"));\n } catch (issueError) {\n // If both fail, throw the issue error (it will have the proper error message)\n throw issueError;\n }\n }\n}\n", "#!/usr/bin/env node\n\n/**\n * sudocode MCP Server entry point\n */\n\nimport { SudocodeMCPServer } from \"./server.js\";\nimport { SudocodeClientConfig } from \"./types.js\";\n\nfunction parseArgs(): SudocodeClientConfig {\n const config: SudocodeClientConfig = {};\n const args = process.argv.slice(2);\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n\n switch (arg) {\n case \"--working-dir\":\n case \"-w\":\n config.workingDir = args[++i];\n break;\n case \"--cli-path\":\n config.cliPath = args[++i];\n break;\n case \"--db-path\":\n case \"--db\":\n config.dbPath = args[++i];\n break;\n case \"--no-sync\":\n config.syncOnStartup = false;\n break;\n case \"--help\":\n case \"-h\":\n console.log(`\nsudocode MCP Server\n\nUsage: sudocode-mcp [options]\n\nOptions:\n -w, --working-dir <path> Working directory (default: cwd or SUDOCODE_WORKING_DIR)\n --cli-path <path> Path to sudocode CLI (default: 'sudocode' or SUDOCODE_PATH)\n --db-path <path> Database path (default: auto-discover or SUDOCODE_DB)\n --no-sync Skip initial sync on startup (default: sync enabled)\n -h, --help Show this help message\n\nEnvironment Variables:\n SUDOCODE_WORKING_DIR Default working directory\n SUDOCODE_PATH Default CLI path\n SUDOCODE_DB Default database path\n `);\n process.exit(0);\n break;\n default:\n console.error(`Unknown option: ${arg}`);\n console.error(\"Use --help for usage information\");\n process.exit(1);\n }\n }\n\n return config;\n}\n\nasync function main() {\n const config = parseArgs();\n const server = new SudocodeMCPServer(config);\n await server.run();\n}\n\nmain().catch((error) => {\n console.error(\"Fatal error:\", error);\n process.exit(1);\n});\n"],
5
+ "mappings": ";AAMA,OAAS,UAAAA,MAAc,4CACvB,OAAS,wBAAAC,MAA4B,4CACrC,OACE,yBAAAC,EACA,8BAAAC,EACA,0BAAAC,EACA,6BAAAC,MACK,qCCNP,OAAS,SAAAC,MAAa,gBACtB,OAAS,iBAAAC,MAAqB,MAC9B,OAAS,WAAAC,EAAS,QAAAC,MAAY,OAC9B,OAAS,cAAAC,MAA4C,KCwD9C,IAAMC,EAAN,cAA4B,KAAM,CACvC,YACEC,EACOC,EACAC,EACP,CACA,MAAMF,CAAO,EAHN,cAAAC,EACA,YAAAC,EAGP,KAAK,KAAO,eACd,CACF,ED9DO,IAAMC,EAAN,KAAqB,CAClB,WACA,QACA,QACA,OACA,eAAiB,GAEzB,YAAYC,EAA+B,CAEzC,IAAIC,EACFD,GAAQ,YAAc,QAAQ,IAAI,sBAAwB,QAAQ,IAAI,GAGpEC,IAAe,sBAAwBA,EAAW,SAAS,IAAI,KACjEA,EAAa,QAAQ,IAAI,KAAO,QAAQ,IAAI,GAG9C,KAAK,WAAaA,EAClB,KAAK,OAASD,GAAQ,QAAU,QAAQ,IAAI,YAG5C,IAAME,EAAU,KAAK,YAAY,EACjC,KAAK,QAAUA,EAAQ,KACvB,KAAK,QAAUA,EAAQ,IACzB,CAMQ,aAAgD,CACtD,GAAI,CACF,IAAMC,EAAcC,EAAc,YAAY,GAAG,EAC3CC,EAAaC,EAAQH,CAAW,EAGhCI,EAAgB,CAEpBC,EACEH,EACA,KACA,KACA,eACA,eACA,MACA,OACA,QACF,EAEAG,EACEH,EACA,KACA,eACA,eACA,MACA,OACA,QACF,CACF,EAEA,QAAWI,KAAaF,EACtB,GAAIG,EAAWD,CAAS,EAEtB,MAAO,CACL,KAAM,QAAQ,SACd,KAAM,CAACA,CAAS,CAClB,CAGN,MAAgB,CAEhB,CAGA,MAAO,CAAE,KAAM,WAAY,KAAM,CAAC,CAAE,CACtC,CAKA,MAAM,KAAKE,EAAgBC,EAA8C,CAElE,KAAK,iBACR,MAAM,KAAK,aAAa,EACxB,KAAK,eAAiB,IAIxB,IAAMC,EAAU,CAAC,GAAG,KAAK,QAAS,GAAGF,CAAI,EAGzC,OAAKE,EAAQ,SAAS,QAAQ,GAC5BA,EAAQ,KAAK,QAAQ,EAInB,KAAK,QAAU,CAACA,EAAQ,SAAS,MAAM,GACzCA,EAAQ,KAAK,OAAQ,KAAK,MAAM,EAG3B,IAAI,QAAQ,CAACC,EAASC,IAAW,CACtC,IAAMC,EAAOC,EAAM,KAAK,QAASJ,EAAS,CACxC,IAAK,KAAK,WACV,IAAK,QAAQ,GACf,CAAC,EAEGK,EAAS,GACTC,EAAS,GAEbH,EAAK,OAAO,GAAG,OAASI,GAAS,CAC/BF,GAAUE,EAAK,SAAS,CAC1B,CAAC,EAEDJ,EAAK,OAAO,GAAG,OAASI,GAAS,CAC/BD,GAAUC,EAAK,SAAS,CAC1B,CAAC,EAGD,IAAMC,EAAUT,GAAS,SAAW,IAC9BU,EAAQ,WAAW,IAAM,CAC7BN,EAAK,KAAK,EACVD,EACE,IAAIQ,EACF,2BAA2BF,CAAO,KAClC,GACA,SACF,CACF,CACF,EAAGA,CAAO,EAEVL,EAAK,GAAG,QAAUQ,GAAS,CAGzB,GAFA,aAAaF,CAAK,EAEdE,IAAS,EAAG,CACdT,EACE,IAAIQ,EACF,qCAAqCC,CAAI,GACzCA,GAAQ,GACRL,CACF,CACF,EACA,MACF,CAGA,GAAI,CACF,IAAMM,EAAS,KAAK,MAAMP,CAAM,EAChCJ,EAAQW,CAAM,CAChB,OAASC,EAAO,CACdX,EACE,IAAIQ,EACF,gCACEG,aAAiB,MAAQA,EAAM,QAAU,OAAOA,CAAK,CACvD,GACA,GACAR,CACF,CACF,CACF,CACF,CAAC,EAEDF,EAAK,GAAG,QAAUU,GAAU,CAC1B,aAAaJ,CAAK,EAClBP,EACE,IAAIQ,EACF,wBAAwBG,EAAM,OAAO,GACrC,GACAA,EAAM,OACR,CACF,CACF,CAAC,CACH,CAAC,CACH,CAKA,MAAM,cAA6C,CACjD,GAAI,CACF,IAAMV,EAAOC,EAAM,KAAK,QAAS,CAAC,GAAG,KAAK,QAAS,WAAW,EAAG,CAC/D,IAAK,KAAK,UACZ,CAAC,EAEGC,EAAS,GACTC,EAAS,GAEb,OAAAH,EAAK,OAAO,GAAG,OAASI,GAAS,CAC/BF,GAAUE,EAAK,SAAS,CAC1B,CAAC,EAEDJ,EAAK,OAAO,GAAG,OAASI,GAAS,CAC/BD,GAAUC,EAAK,SAAS,CAC1B,CAAC,EAEM,IAAI,QAAQ,CAACN,EAASC,IAAW,CACtCC,EAAK,GAAG,QAAUQ,GAAS,CACzB,GAAIA,IAAS,EAAG,CACdT,EACE,IAAIQ,EACF,0FACAC,GAAQ,GACRL,CACF,CACF,EACA,MACF,CAGA,IAAMQ,EAAeT,EAAO,MAAM,iBAAiB,EAC7CU,EAAUD,EAAeA,EAAa,CAAC,EAAIT,EAAO,KAAK,EAE7DJ,EAAQ,CAAE,QAAAc,CAAQ,CAAC,CACrB,CAAC,EAEDZ,EAAK,GAAG,QAAS,IAAM,CACrBD,EACE,IAAIQ,EACF,0BAA0B,KAAK,OAAO,uCACtC,GACA,eACF,CACF,CACF,CAAC,CACH,CAAC,CACH,OAASG,EAAO,CACd,MAAM,IAAIH,EACR,gCACEG,aAAiB,MAAQA,EAAM,QAAU,OAAOA,CAAK,CACvD,GACA,GACA,EACF,CACF,CACF,CACF,EEhNA,eAAsBG,EACpBC,EACAC,EAAsB,CAAC,EACT,CACd,IAAMC,EAAc,MAAMF,EAAO,KAAK,CAAC,OAAO,CAAC,EACzCG,EAAe,MAAMH,EAAO,KAAK,CAAC,QAAQ,CAAC,EAGjD,OAAIE,EAAY,QAAU,MAAM,QAAQA,EAAY,MAAM,IACxDA,EAAY,OAASA,EAAY,OAAO,IAAKE,GAAe,CAC1D,GAAM,CAAE,QAAAC,EAAS,GAAGC,CAAK,EAAIF,EAC7B,OAAOE,CACT,CAAC,GAGI,CACL,MAAOJ,EACP,OAAQC,CACV,CACF,CAKA,eAAsBI,EACpBP,EACAC,EAA2B,CAAC,EACV,CAClB,IAAMO,EAAO,CAAC,QAAS,MAAM,EAEzBP,EAAO,QACTO,EAAK,KAAK,WAAYP,EAAO,MAAM,EAEjCA,EAAO,WAAa,QACtBO,EAAK,KAAK,aAAcP,EAAO,SAAS,SAAS,CAAC,EAEhDA,EAAO,QAAU,QACnBO,EAAK,KAAK,UAAWP,EAAO,MAAM,SAAS,CAAC,EAE1CA,EAAO,QACTO,EAAK,KAAK,SAAUP,EAAO,MAAM,EAGnC,IAAMQ,EAAWR,EAAO,WAAa,OAAYA,EAAO,SAAW,GACnEO,EAAK,KAAK,aAAcC,EAAS,SAAS,CAAC,EAE3C,IAAMC,EAAS,MAAMV,EAAO,KAAKQ,CAAI,EAGrC,OAAI,MAAM,QAAQE,CAAM,EACfA,EAAO,IAAKN,GAAe,CAChC,GAAM,CAAE,QAAAC,EAAS,GAAGC,CAAK,EAAIF,EAC7B,OAAOE,CACT,CAAC,EAGII,CACT,CAKA,eAAsBC,EACpBX,EACAC,EACc,CACd,IAAMO,EAAO,CAAC,QAAS,OAAQP,EAAO,QAAQ,EAC9C,OAAOD,EAAO,KAAKQ,CAAI,CACzB,CAKA,eAAsBI,EACpBZ,EACAC,EACgB,CAGhB,GAFiB,CAAC,CAACA,EAAO,SAEZ,CAEZ,IAAMO,EAAO,CAAC,QAAS,SAAUP,EAAO,QAAS,EAEjD,OAAIA,EAAO,QACTO,EAAK,KAAK,WAAYP,EAAO,MAAM,EAEjCA,EAAO,WAAa,QACtBO,EAAK,KAAK,aAAcP,EAAO,SAAS,SAAS,CAAC,EAEhDA,EAAO,OACTO,EAAK,KAAK,UAAWP,EAAO,KAAK,EAE/BA,EAAO,aACTO,EAAK,KAAK,gBAAiBP,EAAO,WAAW,EAE3CA,EAAO,WAAa,QACtBO,EAAK,KAAK,aAAcP,EAAO,SAAS,SAAS,CAAC,EAG7CD,EAAO,KAAKQ,CAAI,CACzB,KAAO,CAEL,GAAI,CAACP,EAAO,MACV,MAAM,IAAI,MAAM,6CAA6C,EAG/D,IAAMO,EAAO,CAAC,QAAS,SAAUP,EAAO,KAAK,EAE7C,OAAIA,EAAO,aACTO,EAAK,KAAK,gBAAiBP,EAAO,WAAW,EAE3CA,EAAO,WAAa,QACtBO,EAAK,KAAK,aAAcP,EAAO,SAAS,SAAS,CAAC,EAEhDA,EAAO,QACTO,EAAK,KAAK,WAAYP,EAAO,MAAM,EAEjCA,EAAO,MAAQA,EAAO,KAAK,OAAS,GACtCO,EAAK,KAAK,SAAUP,EAAO,KAAK,KAAK,GAAG,CAAC,EAGpCD,EAAO,KAAKQ,CAAI,CACzB,CACF,CCjIA,eAAsBK,EACpBC,EACAC,EAA0B,CAAC,EACV,CACjB,IAAMC,EAAO,CAAC,OAAQ,MAAM,EAExBD,EAAO,QAAU,QACnBC,EAAK,KAAK,UAAWD,EAAO,MAAM,SAAS,CAAC,EAE1CA,EAAO,QACTC,EAAK,KAAK,SAAUD,EAAO,MAAM,EAGnC,IAAME,EAAWF,EAAO,WAAa,OAAYA,EAAO,SAAW,GACnEC,EAAK,KAAK,aAAcC,EAAS,SAAS,CAAC,EAE3C,IAAMC,EAAQ,MAAMJ,EAAO,KAAKE,CAAI,EAGpC,OAAI,MAAM,QAAQE,CAAK,EACdA,EAAM,IAAKC,GAAc,CAC9B,GAAM,CAAE,QAAAC,EAAS,GAAGC,CAAK,EAAIF,EAC7B,OAAOE,CACT,CAAC,EAGIH,CACT,CAKA,eAAsBI,EACpBR,EACAC,EACc,CACd,IAAMC,EAAO,CAAC,OAAQ,OAAQD,EAAO,OAAO,EAC5C,OAAOD,EAAO,KAAKE,CAAI,CACzB,CAKA,eAAsBO,EACpBT,EACAC,EACe,CAGf,GAFiB,CAAC,CAACA,EAAO,QAEZ,CAEZ,IAAMC,EAAO,CAAC,OAAQ,SAAUD,EAAO,OAAQ,EAE/C,OAAIA,EAAO,OACTC,EAAK,KAAK,UAAWD,EAAO,KAAK,EAE/BA,EAAO,WAAa,QACtBC,EAAK,KAAK,aAAcD,EAAO,SAAS,SAAS,CAAC,EAEhDA,EAAO,aACTC,EAAK,KAAK,gBAAiBD,EAAO,WAAW,EAE3CA,EAAO,SAAW,QACpBC,EAAK,KAAK,WAAYD,EAAO,QAAU,EAAE,EAEvCA,EAAO,OAAS,QAClBC,EAAK,KAAK,SAAUD,EAAO,KAAK,KAAK,GAAG,CAAC,EAEvCA,EAAO,WAAa,QACtBC,EAAK,KAAK,aAAcD,EAAO,SAAS,SAAS,CAAC,EAG7CD,EAAO,KAAKE,CAAI,CACzB,KAAO,CAEL,GAAI,CAACD,EAAO,MACV,MAAM,IAAI,MAAM,4CAA4C,EAG9D,IAAMC,EAAO,CAAC,OAAQ,SAAUD,EAAO,KAAK,EAE5C,OAAIA,EAAO,WAAa,QACtBC,EAAK,KAAK,aAAcD,EAAO,SAAS,SAAS,CAAC,EAEhDA,EAAO,aACTC,EAAK,KAAK,gBAAiBD,EAAO,WAAW,EAE3CA,EAAO,QACTC,EAAK,KAAK,WAAYD,EAAO,MAAM,EAEjCA,EAAO,MAAQA,EAAO,KAAK,OAAS,GACtCC,EAAK,KAAK,SAAUD,EAAO,KAAK,KAAK,GAAG,CAAC,EAGpCD,EAAO,KAAKE,CAAI,CACzB,CACF,CCvGA,eAAsBQ,EACpBC,EACAC,EACc,CACd,IAAMC,EAAO,CAAC,OAAQD,EAAO,QAASA,EAAO,KAAK,EAElD,GAAIA,EAAO,UAAYA,EAAO,MAC5B,MAAM,IAAI,MAAM,sCAAsC,EAExD,OAAIA,EAAO,MACTC,EAAK,KAAK,SAAUD,EAAO,IAAI,EAG1BD,EAAO,KAAKE,CAAI,CACzB,CCnBA,eAAsBC,EACpBC,EACAC,EACmB,CACnB,IAAMC,EAAO,CAAC,WAAY,MAAOD,EAAO,SAAUA,EAAO,OAAO,EAEhE,OAAAC,EAAK,KAAK,YAAaD,EAAO,OAAO,EAEjCA,EAAO,MACTC,EAAK,KAAK,SAAUD,EAAO,IAAI,EAE7BA,EAAO,OAAS,QAClBC,EAAK,KAAK,SAAUD,EAAO,KAAK,SAAS,CAAC,EAExCA,EAAO,MACTC,EAAK,KAAK,SAAUD,EAAO,IAAI,EAM1BD,EAAO,KAAKE,CAAI,CACzB,CCpBA,eAAsBC,EACpBC,EACAC,EACc,CAEd,IAAMC,EAAaC,GAA8B,CAC/C,IAAMC,EAAO,CAACD,EAAS,UAAWF,EAAO,UAAWA,EAAO,YAAY,EAEvE,OAAIA,EAAO,OAAS,QAClBG,EAAK,KAAK,SAAUH,EAAO,KAAK,SAAS,CAAC,EAExCA,EAAO,MACTG,EAAK,KAAK,SAAUH,EAAO,IAAI,EAE7BA,EAAO,cACTG,EAAK,KAAK,YAAaH,EAAO,YAAY,EAExCA,EAAO,mBACTG,EAAK,KAAK,SAAUH,EAAO,iBAAiB,EAE1CA,EAAO,QACTG,EAAK,KAAK,WAAYH,EAAO,MAAM,EAEjCA,EAAO,UACTG,EAAK,KAAK,aAAcH,EAAO,QAAQ,EAGlCG,CACT,EAIA,GAAI,CACF,OAAO,MAAMJ,EAAO,KAAKE,EAAU,MAAM,CAAC,CAC5C,MAAoB,CAElB,GAAI,CACF,OAAO,MAAMF,EAAO,KAAKE,EAAU,OAAO,CAAC,CAC7C,OAASG,EAAY,CAEnB,MAAMA,CACR,CACF,CACF,CP7CA,OAAS,cAAAC,MAAkB,KAC3B,OAAS,QAAAC,MAAY,OAEd,IAAMC,EAAN,KAAwB,CACrB,OACA,OACA,OACA,cAAyB,GAEjC,YAAYC,EAA+B,CACzC,KAAK,OAASA,GAAU,CAAC,EACzB,KAAK,OAAS,IAAIC,EAChB,CACE,KAAM,WACN,QAAS,OACX,EACA,CACE,aAAc,CACZ,MAAO,CAAC,EACR,UAAW,CAAC,CACd,CACF,CACF,EAEA,KAAK,OAAS,IAAIC,EAAeF,CAAM,EACvC,KAAK,cAAc,CACrB,CAEQ,eAAgB,CAEtB,KAAK,OAAO,kBAAkBG,EAAwB,UAC7C,CACL,MAAO,CACL,CACE,KAAM,QACN,YACE,sEACF,YAAa,CACX,KAAM,SACN,WAAY,CAAC,CACf,CACF,EACA,CACE,KAAM,cACN,YAAa,wCACb,YAAa,CACX,KAAM,SACN,WAAY,CACV,OAAQ,CACN,KAAM,SACN,KAAM,CAAC,OAAQ,cAAe,UAAW,QAAQ,EACjD,YAAa,6BACf,EACA,SAAU,CACR,KAAM,SACN,YAAa,qCACf,EACA,SAAU,CACR,KAAM,UACN,YACE,6EACJ,EACA,MAAO,CACL,KAAM,SACN,YAAa,yBACb,QAAS,EACX,EACA,OAAQ,CACN,KAAM,SACN,YACE,kDACJ,CACF,CACF,CACF,EACA,CACE,KAAM,aACN,YACE,uEACF,YAAa,CACX,KAAM,SACN,WAAY,CACV,SAAU,CACR,KAAM,SACN,YAAa,8BACf,CACF,EACA,SAAU,CAAC,UAAU,CACvB,CACF,EACA,CACE,KAAM,eACN,YACE,sLACF,YAAa,CACX,KAAM,SACN,WAAY,CACV,SAAU,CACR,KAAM,SACN,YACE,2EACJ,EACA,MAAO,CACL,KAAM,SACN,YACE,wDACJ,EACA,YAAa,CACX,KAAM,SACN,YACE,oIACJ,EACA,SAAU,CACR,KAAM,SACN,YAAa,sCACf,EACA,OAAQ,CACN,KAAM,SACN,YAAa,4BACf,EACA,KAAM,CACJ,KAAM,QACN,MAAO,CAAE,KAAM,QAAS,EACxB,YAAa,iBACf,EACA,OAAQ,CACN,KAAM,SACN,KAAM,CAAC,OAAQ,cAAe,UAAW,QAAQ,EACjD,YAAa,yBACf,EACA,SAAU,CACR,KAAM,UACN,YAAa,2BACf,CACF,CACF,CACF,EACA,CACE,KAAM,aACN,YAAa,uCACb,YAAa,CACX,KAAM,SACN,WAAY,CACV,MAAO,CACL,KAAM,SACN,YAAa,yBACb,QAAS,EACX,EACA,OAAQ,CACN,KAAM,SACN,YACE,iDACJ,CACF,CACF,CACF,EACA,CACE,KAAM,YACN,YACE,6EACF,YAAa,CACX,KAAM,SACN,WAAY,CACV,QAAS,CACP,KAAM,SACN,YAAa,4BACf,CACF,EACA,SAAU,CAAC,SAAS,CACtB,CACF,EACA,CACE,KAAM,cACN,YAAa,sDACb,YAAa,CACX,KAAM,SACN,WAAY,CACV,QAAS,CACP,KAAM,SACN,YACE,yEACJ,EACA,MAAO,CACL,KAAM,SACN,YAAa,kCACf,EACA,SAAU,CACR,KAAM,SACN,YAAa,sCACf,EACA,YAAa,CACX,KAAM,SACN,YAAa,6BACf,EACA,OAAQ,CACN,KAAM,SACN,YAAa,2BACf,EACA,KAAM,CACJ,KAAM,QACN,MAAO,CAAE,KAAM,QAAS,EACxB,YAAa,iBACf,CACF,CACF,CACF,EACA,CACE,KAAM,OACN,YACE,+DACF,YAAa,CACX,KAAM,SACN,WAAY,CACV,QAAS,CACP,KAAM,SACN,YAAa,kBACf,EACA,MAAO,CACL,KAAM,SACN,YAAa,kBACf,EACA,KAAM,CACJ,KAAM,SACN,KAAM,CACJ,SACA,aACA,aACA,aACA,kBACA,SACF,EACA,YAAa,mBACf,CACF,EACA,SAAU,CAAC,UAAW,OAAO,CAC/B,CACF,EACA,CACE,KAAM,gBACN,YACE,qQACF,YAAa,CACX,KAAM,SACN,WAAY,CACV,UAAW,CACT,KAAM,SACN,YAAa,+CACf,EACA,aAAc,CACZ,KAAM,SACN,YAAa,6CACf,EACA,aAAc,CACZ,KAAM,SACN,YAAa,yBACf,EACA,kBAAmB,CACjB,KAAM,SACN,KAAM,CACJ,SACA,aACA,aACA,aACA,kBACA,SACF,EACA,YAAa,8BACf,EACA,KAAM,CACJ,KAAM,SACN,YACE,8DACJ,EACA,KAAM,CACJ,KAAM,SACN,YACE,iEACJ,EACA,OAAQ,CACN,KAAM,SACN,KAAM,CAAC,SAAU,SAAS,EAC1B,YACE,mDACF,QAAS,QACX,CAEF,EACA,SAAU,CAAC,YAAa,cAAc,CACxC,CACF,E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",
6
+ "names": ["Server", "StdioServerTransport", "CallToolRequestSchema", "ListResourcesRequestSchema", "ListToolsRequestSchema", "ReadResourceRequestSchema", "spawn", "fileURLToPath", "dirname", "join", "existsSync", "SudocodeError", "message", "exitCode", "stderr", "SudocodeClient", "config", "workingDir", "cliInfo", "currentFile", "fileURLToPath", "currentDir", "dirname", "possiblePaths", "join", "cliJsPath", "existsSync", "args", "options", "cmdArgs", "resolve", "reject", "proc", "spawn", "stdout", "stderr", "data", "timeout", "timer", "SudocodeError", "code", "result", "error", "versionMatch", "version", "ready", "client", "params", "readyResult", "statusResult", "issue", "content", "rest", "listIssues", "args", "archived", "issues", "showIssue", "upsertIssue", "listSpecs", "client", "params", "args", "archived", "specs", "spec", "content", "rest", "showSpec", "upsertSpec", "link", "client", "params", "args", "addFeedback", "client", "params", "args", "addReference", "client", "params", "buildArgs", "command", "args", "issueError", "existsSync", "join", "SudocodeMCPServer", "config", "Server", "SudocodeClient", "ListToolsRequestSchema", "CallToolRequestSchema", "request", "name", "args", "result", "ready", "listIssues", "showIssue", "upsertIssue", "listSpecs", "showSpec", "upsertSpec", "link", "addReference", "addFeedback", "error", "errorText", "ListResourcesRequestSchema", "ReadResourceRequestSchema", "uri", "workingDir", "sudocodeDir", "cacheDbPath", "issuesPath", "specsPath", "initStatus", "transport", "StdioServerTransport", "parseArgs", "config", "args", "i", "arg", "main", "SudocodeMCPServer", "error"]
7
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * MCP Server for sudocode
3
+ *
4
+ * This module sets up the MCP server with tools and resources.
5
+ */
6
+ import { SudocodeClientConfig } from "./types.js";
7
+ export declare class SudocodeMCPServer {
8
+ private server;
9
+ private client;
10
+ private config;
11
+ private isInitialized;
12
+ constructor(config?: SudocodeClientConfig);
13
+ private setupHandlers;
14
+ /**
15
+ * Check for .sudocode directory and required files
16
+ * Returns initialization status and handles auto-import if needed
17
+ */
18
+ private checkForInit;
19
+ /**
20
+ * Check if sudocode is initialized in the working directory
21
+ * This provides early warning to users without blocking server startup
22
+ */
23
+ private checkInitialization;
24
+ run(): Promise<void>;
25
+ }
26
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAgBH,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAIlD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,aAAa,CAAkB;gBAE3B,MAAM,CAAC,EAAE,oBAAoB;IAmBzC,OAAO,CAAC,aAAa;IAmerB;;;OAGG;YACW,YAAY;IA2E1B;;;OAGG;YACW,mBAAmB;IA8B3B,GAAG;CAQV"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * MCP tools for analytics and statistics
3
+ */
4
+ import { SudocodeClient } from "../client.js";
5
+ export interface StatusParams {
6
+ verbose?: boolean;
7
+ }
8
+ export interface StatsResult {
9
+ specs: {
10
+ total: number;
11
+ by_status: Record<string, number>;
12
+ by_type: Record<string, number>;
13
+ ready: number;
14
+ };
15
+ issues: {
16
+ total: number;
17
+ by_status: Record<string, number>;
18
+ by_type: Record<string, number>;
19
+ ready: number;
20
+ blocked: number;
21
+ };
22
+ relationships: {
23
+ total: number;
24
+ by_type: Record<string, number>;
25
+ };
26
+ recent_activity: {
27
+ specs_updated: number;
28
+ issues_updated: number;
29
+ issues_created: number;
30
+ issues_closed: number;
31
+ };
32
+ }
33
+ /**
34
+ * Get comprehensive project statistics
35
+ */
36
+ export declare function stats(client: SudocodeClient): Promise<StatsResult>;
37
+ /**
38
+ * Get quick project status
39
+ */
40
+ export declare function status(client: SudocodeClient, params?: StatusParams): Promise<any>;
41
+ //# sourceMappingURL=analytics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../src/tools/analytics.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAGD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE;QACL,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAClC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAChC,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAClC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAChC,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,aAAa,EAAE;QACb,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACjC,CAAC;IACF,eAAe,EAAE;QACf,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC;QACvB,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;CACH;AAID;;GAEG;AACH,wBAAsB,KAAK,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CAExE;AAED;;GAEG;AACH,wBAAsB,MAAM,CAC1B,MAAM,EAAE,cAAc,EACtB,MAAM,GAAE,YAAiB,GACxB,OAAO,CAAC,GAAG,CAAC,CAQd"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * MCP tools for feedback management
3
+ */
4
+ import { SudocodeClient } from "../client.js";
5
+ import { Feedback, FeedbackType } from "../types.js";
6
+ export interface AddFeedbackParams {
7
+ issue_id: string;
8
+ spec_id: string;
9
+ content: string;
10
+ type?: FeedbackType;
11
+ line?: number;
12
+ text?: string;
13
+ agent?: string;
14
+ }
15
+ /**
16
+ * Add anchored feedback to a spec
17
+ */
18
+ export declare function addFeedback(client: SudocodeClient, params: AddFeedbackParams): Promise<Feedback>;
19
+ //# sourceMappingURL=feedback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feedback.d.ts","sourceRoot":"","sources":["../../src/tools/feedback.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGrD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,QAAQ,CAAC,CAmBnB"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * MCP tool for initialization
3
+ */
4
+ import { SudocodeClient } from "../client.js";
5
+ export interface InitParams {
6
+ prefix?: string;
7
+ }
8
+ export interface InitResult {
9
+ success: boolean;
10
+ path: string;
11
+ prefix: string;
12
+ }
13
+ /**
14
+ * Initialize sudocode in the current directory
15
+ */
16
+ export declare function init(client: SudocodeClient, params?: InitParams): Promise<InitResult>;
17
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/tools/init.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAGD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAID;;GAEG;AACH,wBAAsB,IAAI,CACxB,MAAM,EAAE,cAAc,EACtB,MAAM,GAAE,UAAe,GACtB,OAAO,CAAC,UAAU,CAAC,CAQrB"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * MCP tools for issue management
3
+ */
4
+ import { SudocodeClient } from "../client.js";
5
+ import { Issue, IssueStatus } from "../types.js";
6
+ export interface ReadyParams {
7
+ }
8
+ export interface ListIssuesParams {
9
+ status?: IssueStatus;
10
+ priority?: number;
11
+ limit?: number;
12
+ search?: string;
13
+ archived?: boolean;
14
+ }
15
+ export interface ShowIssueParams {
16
+ issue_id: string;
17
+ }
18
+ export interface UpsertIssueParams {
19
+ issue_id?: string;
20
+ title?: string;
21
+ description?: string;
22
+ priority?: number;
23
+ parent?: string;
24
+ tags?: string[];
25
+ status?: IssueStatus;
26
+ archived?: boolean;
27
+ }
28
+ /**
29
+ * Find issues ready to work on (no blockers) and get project status
30
+ */
31
+ export declare function ready(client: SudocodeClient, params?: ReadyParams): Promise<any>;
32
+ /**
33
+ * List all issues with optional filters
34
+ */
35
+ export declare function listIssues(client: SudocodeClient, params?: ListIssuesParams): Promise<Issue[]>;
36
+ /**
37
+ * Show detailed issue information including relationships and feedback
38
+ */
39
+ export declare function showIssue(client: SudocodeClient, params: ShowIssueParams): Promise<any>;
40
+ /**
41
+ * Upsert an issue (create if no issue_id, update if issue_id provided)
42
+ */
43
+ export declare function upsertIssue(client: SudocodeClient, params: UpsertIssueParams): Promise<Issue>;
44
+ //# sourceMappingURL=issues.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issues.d.ts","sourceRoot":"","sources":["../../src/tools/issues.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAGjD,MAAM,WAAW,WAAW;CAAG;AAE/B,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CAEpB;AAID;;GAEG;AACH,wBAAsB,KAAK,CACzB,MAAM,EAAE,cAAc,EACtB,MAAM,GAAE,WAAgB,GACvB,OAAO,CAAC,GAAG,CAAC,CAgBd;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,cAAc,EACtB,MAAM,GAAE,gBAAqB,GAC5B,OAAO,CAAC,KAAK,EAAE,CAAC,CA8BlB;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC,GAAG,CAAC,CAGd;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,KAAK,CAAC,CA+ChB"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * MCP tools for reference management
3
+ */
4
+ import { SudocodeClient } from "../client.js";
5
+ export interface AddReferenceParams {
6
+ entity_id: string;
7
+ reference_id: string;
8
+ display_text?: string;
9
+ relationship_type?: string;
10
+ line?: number;
11
+ text?: string;
12
+ format?: "inline" | "newline";
13
+ position?: "before" | "after";
14
+ }
15
+ /**
16
+ * Add a cross-reference to a spec or issue
17
+ *
18
+ * Tries spec first, then issue. The CLI command handles entity validation.
19
+ */
20
+ export declare function addReference(client: SudocodeClient, params: AddReferenceParams): Promise<any>;
21
+ //# sourceMappingURL=references.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"references.d.ts","sourceRoot":"","sources":["../../src/tools/references.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC9B,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;CAC/B;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,GAAG,CAAC,CAwCd"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * MCP tools for relationship management
3
+ */
4
+ import { SudocodeClient } from "../client.js";
5
+ export type RelationshipType = "blocks" | "implements" | "references" | "depends-on" | "discovered-from" | "related";
6
+ export interface LinkParams {
7
+ from_id: string;
8
+ to_id: string;
9
+ type?: RelationshipType;
10
+ }
11
+ /**
12
+ * Create a relationship between two entities (specs or issues)
13
+ */
14
+ export declare function link(client: SudocodeClient, params: LinkParams): Promise<any>;
15
+ //# sourceMappingURL=relationships.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relationships.d.ts","sourceRoot":"","sources":["../../src/tools/relationships.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,MAAM,MAAM,gBAAgB,GACxB,QAAQ,GACR,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,iBAAiB,GACjB,SAAS,CAAC;AAEd,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,gBAAgB,CAAC;CACzB;AAID;;GAEG;AACH,wBAAsB,IAAI,CACxB,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,GAAG,CAAC,CAWd"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * MCP tools for spec management
3
+ */
4
+ import { SudocodeClient } from "../client.js";
5
+ import { Spec } from "../types.js";
6
+ export interface ListSpecsParams {
7
+ limit?: number;
8
+ search?: string;
9
+ archived?: boolean;
10
+ }
11
+ export interface ShowSpecParams {
12
+ spec_id: string;
13
+ }
14
+ export interface UpsertSpecParams {
15
+ spec_id?: string;
16
+ title?: string;
17
+ priority?: number;
18
+ description?: string;
19
+ parent?: string;
20
+ tags?: string[];
21
+ archived?: boolean;
22
+ }
23
+ /**
24
+ * List all specs with optional filters
25
+ */
26
+ export declare function listSpecs(client: SudocodeClient, params?: ListSpecsParams): Promise<Spec[]>;
27
+ /**
28
+ * Show detailed spec information including feedback
29
+ */
30
+ export declare function showSpec(client: SudocodeClient, params: ShowSpecParams): Promise<any>;
31
+ /**
32
+ * Upsert a spec (create if no spec_id, update if spec_id provided)
33
+ */
34
+ export declare function upsertSpec(client: SudocodeClient, params: UpsertSpecParams): Promise<Spec>;
35
+ //# sourceMappingURL=specs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"specs.d.ts","sourceRoot":"","sources":["../../src/tools/specs.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGnC,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAID;;GAEG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,cAAc,EACtB,MAAM,GAAE,eAAoB,GAC3B,OAAO,CAAC,IAAI,EAAE,CAAC,CAwBjB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,GAAG,CAAC,CAGd;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,IAAI,CAAC,CAkDf"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Type definitions for sudocode MCP server
3
+ *
4
+ * Core entity types are imported from the main sudocode package.
5
+ * This file contains MCP-specific types and some forward-compatible types
6
+ * for fields that may be added to the core package in the future.
7
+ */
8
+ export type { Spec, Issue, Relationship, EntityType, RelationshipType, IssueStatus, FeedbackAnchor, FeedbackType, IssueFeedback as Feedback, } from "@sudocode-ai/types";
9
+ /**
10
+ * Issue type classification
11
+ * NOTE: Not yet stored in database or supported by CLI filtering
12
+ */
13
+ export type IssueType = "bug" | "feature" | "task" | "epic" | "chore";
14
+ /**
15
+ * Spec status lifecycle
16
+ * NOTE: Not yet stored in database or supported by CLI filtering
17
+ */
18
+ export type SpecStatus = "draft" | "review" | "approved" | "deprecated";
19
+ /**
20
+ * Spec type classification
21
+ * NOTE: Not yet stored in database or supported by CLI filtering
22
+ */
23
+ export type SpecType = "architecture" | "api" | "database" | "feature" | "research";
24
+ export interface SudocodeClientConfig {
25
+ workingDir?: string;
26
+ cliPath?: string;
27
+ dbPath?: string;
28
+ syncOnStartup?: boolean;
29
+ }
30
+ export declare class SudocodeError extends Error {
31
+ exitCode: number;
32
+ stderr: string;
33
+ constructor(message: string, exitCode: number, stderr: string);
34
+ }
35
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,YAAY,EACV,IAAI,EACJ,KAAK,EACL,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,YAAY,EACZ,aAAa,IAAI,QAAQ,GAC1B,MAAM,oBAAoB,CAAC;AAS5B;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAEtE;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,YAAY,CAAC;AAExE;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAChB,cAAc,GACd,KAAK,GACL,UAAU,GACV,SAAS,GACT,UAAU,CAAC;AAMf,MAAM,WAAW,oBAAoB;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAMD,qBAAa,aAAc,SAAQ,KAAK;IAG7B,QAAQ,EAAE,MAAM;IAChB,MAAM,EAAE,MAAM;gBAFrB,OAAO,EAAE,MAAM,EACR,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM;CAKxB"}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@sudocode-ai/mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for sudocode, git-native context management for AI-assisted development",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "sudocode-mcp": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist/**/*",
12
+ "README.md",
13
+ "LICENSE"
14
+ ],
15
+ "scripts": {
16
+ "build": "node build.js",
17
+ "build:dev": "tsc",
18
+ "dev": "tsc --watch",
19
+ "test": "vitest",
20
+ "test:unit": "vitest run tests/unit",
21
+ "test:integration": "vitest run tests/integration",
22
+ "clean": "rm -rf dist"
23
+ },
24
+ "keywords": [
25
+ "mcp",
26
+ "model-context-protocol",
27
+ "sudocode",
28
+ "project-management",
29
+ "specs",
30
+ "context-as-code",
31
+ "specifications",
32
+ "spec-driven-development",
33
+ "issues",
34
+ "issue-tracking",
35
+ "ai-assisted-development",
36
+ "coding-agent",
37
+ "git-native"
38
+ ],
39
+ "author": "sudocode AI",
40
+ "license": "Apache-2.0",
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "git+https://github.com/sudocode-ai/sudocode.git",
44
+ "directory": "mcp"
45
+ },
46
+ "homepage": "https://sudocode.ai",
47
+ "bugs": {
48
+ "url": "https://github.com/sudocode-ai/sudocode/issues"
49
+ },
50
+ "publishConfig": {
51
+ "access": "public"
52
+ },
53
+ "engines": {
54
+ "node": ">=18.0.0"
55
+ },
56
+ "dependencies": {
57
+ "@modelcontextprotocol/sdk": "^1.0.4",
58
+ "@sudocode-ai/cli": "^0.1.0",
59
+ "@sudocode-ai/types": "^0.1.0",
60
+ "vite": "7.1.12"
61
+ },
62
+ "devDependencies": {
63
+ "@types/node": "^20.10.6",
64
+ "esbuild": "^0.24.2",
65
+ "typescript": "^5.3.3",
66
+ "vitest": "^3.2.4"
67
+ }
68
+ }