Skip to content

Commit c23b2a5

Browse files
author
Marvin Zhang
committed
fix: mcp misaligned paramters issues
1 parent e3d832e commit c23b2a5

File tree

12 files changed

+148
-147
lines changed

12 files changed

+148
-147
lines changed

rust/leanspec-mcp/src/tools.rs

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@ pub fn get_tool_definitions() -> Vec<ToolDefinition> {
3838
input_schema: json!({
3939
"type": "object",
4040
"properties": {
41-
"spec": {
41+
"specPath": {
4242
"type": "string",
4343
"description": "Spec path or number (e.g., '170' or '170-cli-mcp')"
4444
}
4545
},
46-
"required": ["spec"],
46+
"required": ["specPath"],
4747
"additionalProperties": false
4848
}),
4949
},
@@ -88,7 +88,7 @@ pub fn get_tool_definitions() -> Vec<ToolDefinition> {
8888
input_schema: json!({
8989
"type": "object",
9090
"properties": {
91-
"spec": {
91+
"specPath": {
9292
"type": "string",
9393
"description": "Spec path or number"
9494
},
@@ -117,7 +117,7 @@ pub fn get_tool_definitions() -> Vec<ToolDefinition> {
117117
"description": "Tags to remove"
118118
}
119119
},
120-
"required": ["spec"],
120+
"required": ["specPath"],
121121
"additionalProperties": false
122122
}),
123123
},
@@ -127,7 +127,7 @@ pub fn get_tool_definitions() -> Vec<ToolDefinition> {
127127
input_schema: json!({
128128
"type": "object",
129129
"properties": {
130-
"spec": {
130+
"specPath": {
131131
"type": "string",
132132
"description": "Specific spec to validate (validates all if not provided)"
133133
},
@@ -146,7 +146,7 @@ pub fn get_tool_definitions() -> Vec<ToolDefinition> {
146146
input_schema: json!({
147147
"type": "object",
148148
"properties": {
149-
"spec": {
149+
"specPath": {
150150
"type": "string",
151151
"description": "Spec path or number"
152152
},
@@ -156,7 +156,7 @@ pub fn get_tool_definitions() -> Vec<ToolDefinition> {
156156
"default": 3
157157
}
158158
},
159-
"required": ["spec"],
159+
"required": ["specPath"],
160160
"additionalProperties": false
161161
}),
162162
},
@@ -166,7 +166,7 @@ pub fn get_tool_definitions() -> Vec<ToolDefinition> {
166166
input_schema: json!({
167167
"type": "object",
168168
"properties": {
169-
"spec": {
169+
"specPath": {
170170
"type": "string",
171171
"description": "Spec to link from"
172172
},
@@ -175,7 +175,7 @@ pub fn get_tool_definitions() -> Vec<ToolDefinition> {
175175
"description": "Spec to depend on"
176176
}
177177
},
178-
"required": ["spec", "dependsOn"],
178+
"required": ["specPath", "dependsOn"],
179179
"additionalProperties": false
180180
}),
181181
},
@@ -185,7 +185,7 @@ pub fn get_tool_definitions() -> Vec<ToolDefinition> {
185185
input_schema: json!({
186186
"type": "object",
187187
"properties": {
188-
"spec": {
188+
"specPath": {
189189
"type": "string",
190190
"description": "Spec to unlink from"
191191
},
@@ -194,7 +194,7 @@ pub fn get_tool_definitions() -> Vec<ToolDefinition> {
194194
"description": "Spec to remove from dependencies"
195195
}
196196
},
197-
"required": ["spec", "dependsOn"],
197+
"required": ["specPath", "dependsOn"],
198198
"additionalProperties": false
199199
}),
200200
},
@@ -240,7 +240,7 @@ pub fn get_tool_definitions() -> Vec<ToolDefinition> {
240240
input_schema: json!({
241241
"type": "object",
242242
"properties": {
243-
"spec": {
243+
"specPath": {
244244
"type": "string",
245245
"description": "Specific spec (counts all if not provided)"
246246
}
@@ -325,9 +325,9 @@ fn tool_list(specs_dir: &str, args: Value) -> Result<String, String> {
325325
}
326326

327327
fn tool_view(specs_dir: &str, args: Value) -> Result<String, String> {
328-
let spec_path = args.get("spec")
328+
let spec_path = args.get("specPath")
329329
.and_then(|v| v.as_str())
330-
.ok_or("Missing required parameter: spec")?;
330+
.ok_or("Missing required parameter: specPath")?;
331331

332332
let loader = SpecLoader::new(specs_dir);
333333
let spec = loader.load(spec_path).map_err(|e| e.to_string())?
@@ -389,9 +389,9 @@ fn tool_create(specs_dir: &str, args: Value) -> Result<String, String> {
389389
}
390390

391391
fn tool_update(specs_dir: &str, args: Value) -> Result<String, String> {
392-
let spec_path = args.get("spec")
392+
let spec_path = args.get("specPath")
393393
.and_then(|v| v.as_str())
394-
.ok_or("Missing required parameter: spec")?;
394+
.ok_or("Missing required parameter: specPath")?;
395395

396396
let loader = SpecLoader::new(specs_dir);
397397
let spec = loader.load(spec_path).map_err(|e| e.to_string())?
@@ -475,7 +475,7 @@ fn tool_validate(specs_dir: &str, args: Value) -> Result<String, String> {
475475

476476
let mut issues = Vec::new();
477477

478-
let specs_to_validate = if let Some(spec_path) = args.get("spec").and_then(|v| v.as_str()) {
478+
let specs_to_validate = if let Some(spec_path) = args.get("specPath").and_then(|v| v.as_str()) {
479479
let spec = loader.load(spec_path).map_err(|e| e.to_string())?
480480
.ok_or_else(|| format!("Spec not found: {}", spec_path))?;
481481
vec![spec]
@@ -509,9 +509,9 @@ fn tool_validate(specs_dir: &str, args: Value) -> Result<String, String> {
509509
}
510510

511511
fn tool_deps(specs_dir: &str, args: Value) -> Result<String, String> {
512-
let spec_path = args.get("spec")
512+
let spec_path = args.get("specPath")
513513
.and_then(|v| v.as_str())
514-
.ok_or("Missing required parameter: spec")?;
514+
.ok_or("Missing required parameter: specPath")?;
515515

516516
let _depth = args.get("depth").and_then(|v| v.as_u64()).unwrap_or(3) as usize;
517517

@@ -545,9 +545,9 @@ fn tool_deps(specs_dir: &str, args: Value) -> Result<String, String> {
545545
}
546546

547547
fn tool_link(specs_dir: &str, args: Value) -> Result<String, String> {
548-
let spec_path = args.get("spec")
548+
let spec_path = args.get("specPath")
549549
.and_then(|v| v.as_str())
550-
.ok_or("Missing required parameter: spec")?;
550+
.ok_or("Missing required parameter: specPath")?;
551551

552552
let depends_on = args.get("dependsOn")
553553
.and_then(|v| v.as_str())
@@ -587,9 +587,9 @@ fn tool_link(specs_dir: &str, args: Value) -> Result<String, String> {
587587
}
588588

589589
fn tool_unlink(specs_dir: &str, args: Value) -> Result<String, String> {
590-
let spec_path = args.get("spec")
590+
let spec_path = args.get("specPath")
591591
.and_then(|v| v.as_str())
592-
.ok_or("Missing required parameter: spec")?;
592+
.ok_or("Missing required parameter: specPath")?;
593593

594594
let depends_on = args.get("dependsOn")
595595
.and_then(|v| v.as_str())
@@ -736,7 +736,7 @@ fn tool_tokens(specs_dir: &str, args: Value) -> Result<String, String> {
736736
let loader = SpecLoader::new(specs_dir);
737737
let counter = TokenCounter::new();
738738

739-
if let Some(spec_path) = args.get("spec").and_then(|v| v.as_str()) {
739+
if let Some(spec_path) = args.get("specPath").and_then(|v| v.as_str()) {
740740
let spec = loader.load(spec_path).map_err(|e| e.to_string())?
741741
.ok_or_else(|| format!("Spec not found: {}", spec_path))?;
742742

rust/leanspec-mcp/tests/integration/e2e.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ async fn test_tool_error() {
115115
"params": {
116116
"name": "view",
117117
"arguments": {
118-
"spec": "nonexistent"
118+
"specPath": "nonexistent"
119119
}
120120
}
121121
}))

rust/leanspec-mcp/tests/integration/workflows.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ async fn test_create_link_update_validate_workflow() {
2828
let update_result = call_tool(
2929
"update",
3030
json!({
31-
"spec": "002",
31+
"specPath": "002",
3232
"status": "in-progress"
3333
}),
3434
)
@@ -62,14 +62,14 @@ async fn test_search_view_update_workflow() {
6262
}
6363

6464
// Step 2: View by spec number instead of path from search
65-
let view_result = call_tool("view", json!({ "spec": "001" })).await;
65+
let view_result = call_tool("view", json!({ "specPath": "001" })).await;
6666
assert!(view_result.is_ok());
6767

6868
// Step 3: Update the viewed spec
6969
let update_result = call_tool(
7070
"update",
7171
json!({
72-
"spec": "001",
72+
"specPath": "001",
7373
"status": "in-progress",
7474
"addTags": ["security"]
7575
}),
@@ -101,7 +101,7 @@ async fn test_board_list_view_workflow() {
101101
assert!(list_output["count"].is_number());
102102

103103
// Step 3: View a known spec
104-
let view_result = call_tool("view", json!({ "spec": "001" })).await;
104+
let view_result = call_tool("view", json!({ "specPath": "001" })).await;
105105
assert!(view_result.is_ok());
106106
}
107107

@@ -141,15 +141,15 @@ async fn test_link_deps_unlink_workflow() {
141141
let link_result = call_tool(
142142
"link",
143143
json!({
144-
"spec": "002",
144+
"specPath": "002",
145145
"dependsOn": "001"
146146
}),
147147
)
148148
.await;
149149
assert!(link_result.is_ok());
150150

151151
// Step 2: Check dependencies
152-
let deps_result = call_tool("deps", json!({ "spec": "002" })).await;
152+
let deps_result = call_tool("deps", json!({ "specPath": "002" })).await;
153153
assert!(deps_result.is_ok());
154154

155155
let deps_output: serde_json::Value =
@@ -161,7 +161,7 @@ async fn test_link_deps_unlink_workflow() {
161161
let unlink_result = call_tool(
162162
"unlink",
163163
json!({
164-
"spec": "002-feature",
164+
"specPath": "002-feature",
165165
"dependsOn": "001-base"
166166
}),
167167
)

rust/leanspec-mcp/tests/tools/deps.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ async fn test_deps_show_dependencies() {
1515
]);
1616
set_specs_dir_env(&temp);
1717

18-
let result = call_tool("deps", json!({ "spec": "002" })).await;
18+
let result = call_tool("deps", json!({ "specPath": "002" })).await;
1919
assert!(result.is_ok());
2020

2121
let output: serde_json::Value = serde_json::from_str(&result.unwrap()).unwrap();
@@ -32,7 +32,7 @@ async fn test_deps_show_required_by() {
3232
]);
3333
set_specs_dir_env(&temp);
3434

35-
let result = call_tool("deps", json!({ "spec": "001" })).await;
35+
let result = call_tool("deps", json!({ "specPath": "001" })).await;
3636
assert!(result.is_ok());
3737

3838
let output: serde_json::Value = serde_json::from_str(&result.unwrap()).unwrap();
@@ -46,7 +46,7 @@ async fn test_deps_no_dependencies() {
4646
let temp = create_test_project(&[("001-feature-a", "planned", None)]);
4747
set_specs_dir_env(&temp);
4848

49-
let result = call_tool("deps", json!({ "spec": "001" })).await;
49+
let result = call_tool("deps", json!({ "specPath": "001" })).await;
5050
assert!(result.is_ok());
5151

5252
let output: serde_json::Value = serde_json::from_str(&result.unwrap()).unwrap();
@@ -63,7 +63,7 @@ async fn test_deps_with_depth() {
6363
]);
6464
set_specs_dir_env(&temp);
6565

66-
let result = call_tool("deps", json!({ "spec": "003", "depth": 2 })).await;
66+
let result = call_tool("deps", json!({ "specPath": "003", "depth": 2 })).await;
6767
assert!(result.is_ok());
6868

6969
let output: serde_json::Value = serde_json::from_str(&result.unwrap()).unwrap();
@@ -97,7 +97,7 @@ async fn test_deps_circular_detection() {
9797

9898
set_specs_dir_env(&temp);
9999

100-
let result = call_tool("deps", json!({ "spec": "001" })).await;
100+
let result = call_tool("deps", json!({ "specPath": "001" })).await;
101101
assert!(result.is_ok());
102102

103103
let output: serde_json::Value = serde_json::from_str(&result.unwrap()).unwrap();
@@ -109,7 +109,7 @@ async fn test_deps_spec_not_found() {
109109
let temp = create_test_project(&[("001-feature-a", "planned", None)]);
110110
set_specs_dir_env(&temp);
111111

112-
let result = call_tool("deps", json!({ "spec": "999" })).await;
112+
let result = call_tool("deps", json!({ "specPath": "999" })).await;
113113
assert!(result.is_err());
114114
assert!(result.unwrap_err().contains("not found"));
115115
}
@@ -132,7 +132,7 @@ async fn test_deps_output_structure() {
132132
]);
133133
set_specs_dir_env(&temp);
134134

135-
let result = call_tool("deps", json!({ "spec": "002" })).await;
135+
let result = call_tool("deps", json!({ "specPath": "002" })).await;
136136
assert!(result.is_ok());
137137

138138
let output: serde_json::Value = serde_json::from_str(&result.unwrap()).unwrap();

rust/leanspec-mcp/tests/tools/link.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ async fn test_link_two_specs() {
1818
let result = call_tool(
1919
"link",
2020
json!({
21-
"spec": "002",
21+
"specPath": "002",
2222
"dependsOn": "001"
2323
}),
2424
)
@@ -43,7 +43,7 @@ async fn test_link_already_linked() {
4343
let result = call_tool(
4444
"link",
4545
json!({
46-
"spec": "002",
46+
"specPath": "002",
4747
"dependsOn": "001"
4848
}),
4949
)
@@ -60,7 +60,7 @@ async fn test_link_spec_not_found() {
6060
let result = call_tool(
6161
"link",
6262
json!({
63-
"spec": "999",
63+
"specPath": "999",
6464
"dependsOn": "001"
6565
}),
6666
)
@@ -77,7 +77,7 @@ async fn test_link_target_not_found() {
7777
let result = call_tool(
7878
"link",
7979
json!({
80-
"spec": "001",
80+
"specPath": "001",
8181
"dependsOn": "999"
8282
}),
8383
)
@@ -101,7 +101,7 @@ async fn test_link_missing_depends_on_param() {
101101
let temp = create_test_project(&[("001-base", "complete", None)]);
102102
set_specs_dir_env(&temp);
103103

104-
let result = call_tool("link", json!({ "spec": "001" })).await;
104+
let result = call_tool("link", json!({ "specPath": "001" })).await;
105105
assert!(result.is_err());
106106
assert!(result
107107
.unwrap_err()
@@ -121,7 +121,7 @@ async fn test_link_multiple_dependencies() {
121121
let result1 = call_tool(
122122
"link",
123123
json!({
124-
"spec": "003",
124+
"specPath": "003",
125125
"dependsOn": "001"
126126
}),
127127
)
@@ -132,7 +132,7 @@ async fn test_link_multiple_dependencies() {
132132
let result2 = call_tool(
133133
"link",
134134
json!({
135-
"spec": "003",
135+
"specPath": "003",
136136
"dependsOn": "002"
137137
}),
138138
)
@@ -157,7 +157,7 @@ async fn test_link_by_full_path() {
157157
let result = call_tool(
158158
"link",
159159
json!({
160-
"spec": "002-feature",
160+
"specPath": "002-feature",
161161
"dependsOn": "001-base"
162162
}),
163163
)

0 commit comments

Comments
 (0)