feat(auto-mirror): wrap 13 modifying tools so --auto-mirror actually works
The 75cf74d scaffold added the helpers; this commit makes them
load-bearing by switching every modifying tool's formatToolResponse
call to formatModifyingResponse. Without --auto-mirror, behaviour is
unchanged. With it: mirror_export runs after each successful edit and
'code --add <mirror>' fires once per project to surface the diff in
VSCode's Source Control panel.
This commit is contained in:
parent
4f5c80e591
commit
0fa9b3852b
2 changed files with 69 additions and 23 deletions
26
README.md
26
README.md
|
|
@ -68,6 +68,32 @@ See [Installation](#installation) for source-install / upgrade / multi-install s
|
|||
|
||||
---
|
||||
|
||||
## Live source-control diff (`--auto-mirror`)
|
||||
|
||||
When `--auto-mirror` is added to the server args, every successful modifying tool call (`set_pou_code`, `create_pou`, `rename_object`, `add_library`, ...) is followed by an automatic `mirror_export`. The textual `<projectDir>/mcp-mirror/` tree is refreshed on disk in lock-step with the binary `.project`, so an external editor watching the folder sees the change immediately. The first refresh on a given project also fires `code --add <mirrorDir>` once, which appends the mirror folder to your active VSCode window so the diff shows up in the Source Control panel.
|
||||
|
||||
Enable it by adding the flag to the relevant entry's `args` in `.mcp.json`:
|
||||
|
||||
```jsonc
|
||||
"args": [
|
||||
"--codesys-path", "...",
|
||||
"--codesys-profile", "...",
|
||||
"--mode", "persistent",
|
||||
"--auto-mirror"
|
||||
]
|
||||
```
|
||||
|
||||
Recommended one-time setup so the Source Control panel has a baseline to diff against:
|
||||
|
||||
```bash
|
||||
cd <projectDir>/mcp-mirror
|
||||
git init && git add -A && git commit -m "baseline"
|
||||
```
|
||||
|
||||
After that, watch VSCode's Source Control panel as Claude edits — every tool call shows up as a real diff. The VSCode hook is best-effort: if the `code` CLI shim isn't on the standard path, the mirror still refreshes silently and the response carries an `(auto-mirror: refreshed)` hint instead of opening a window.
|
||||
|
||||
---
|
||||
|
||||
## What's new in this fork
|
||||
|
||||
### Compatibility fixes (the headline)
|
||||
|
|
|
|||
|
|
@ -839,7 +839,7 @@ export async function startMcpServer(config: ServerConfig): Promise<void> {
|
|||
'open_project', { PROJECT_FILE_PATH: escaped }, ['ensure_project_open']
|
||||
);
|
||||
const result = await executor.executeScript(script);
|
||||
return formatToolResponse(result, `Project opened: ${args.filePath}`);
|
||||
return await formatModifyingResponse(result, `Project opened: ${args.filePath}`, escaped, mirrorCtx);
|
||||
}
|
||||
);
|
||||
|
||||
|
|
@ -886,7 +886,7 @@ export async function startMcpServer(config: ServerConfig): Promise<void> {
|
|||
TEMPLATE_PROJECT_PATH: templatePath,
|
||||
});
|
||||
const result = await executor.executeScript(script);
|
||||
return formatToolResponse(result, `Project created from template: ${absPath}`);
|
||||
return await formatModifyingResponse(result, `Project created from template: ${absPath}`, absPath, mirrorCtx);
|
||||
}
|
||||
);
|
||||
|
||||
|
|
@ -902,7 +902,7 @@ export async function startMcpServer(config: ServerConfig): Promise<void> {
|
|||
'save_project', { PROJECT_FILE_PATH: escaped }, ['ensure_project_open']
|
||||
);
|
||||
const result = await executor.executeScript(script);
|
||||
return formatToolResponse(result, `Project saved: ${args.projectFilePath}`);
|
||||
return await formatModifyingResponse(result, `Project saved: ${args.projectFilePath}`, escaped, mirrorCtx);
|
||||
}
|
||||
);
|
||||
|
||||
|
|
@ -933,9 +933,11 @@ export async function startMcpServer(config: ServerConfig): Promise<void> {
|
|||
['ensure_project_open', 'find_object_by_path']
|
||||
);
|
||||
const result = await executor.executeScript(script);
|
||||
return formatToolResponse(
|
||||
return await formatModifyingResponse(
|
||||
result,
|
||||
`POU '${args.name}' created in '${sanParentPath}' of ${args.projectFilePath}. Project saved.`
|
||||
`POU '${args.name}' created in '${sanParentPath}' of ${args.projectFilePath}. Project saved.`,
|
||||
escProjPath,
|
||||
mirrorCtx
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
@ -992,9 +994,11 @@ export async function startMcpServer(config: ServerConfig): Promise<void> {
|
|||
['ensure_project_open', 'find_object_by_path']
|
||||
);
|
||||
const result = await executor.executeScript(script);
|
||||
return formatToolResponse(
|
||||
return await formatModifyingResponse(
|
||||
result,
|
||||
`Code set for '${sanPouPath}' in ${args.projectFilePath}. Project saved.`
|
||||
`Code set for '${sanPouPath}' in ${args.projectFilePath}. Project saved.`,
|
||||
escProjPath,
|
||||
mirrorCtx
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
@ -1022,9 +1026,11 @@ export async function startMcpServer(config: ServerConfig): Promise<void> {
|
|||
['ensure_project_open', 'find_object_by_path']
|
||||
);
|
||||
const result = await executor.executeScript(script);
|
||||
return formatToolResponse(
|
||||
return await formatModifyingResponse(
|
||||
result,
|
||||
`Property '${args.propertyName}' created under '${sanParentPath}' in ${args.projectFilePath}. Project saved.`
|
||||
`Property '${args.propertyName}' created under '${sanParentPath}' in ${args.projectFilePath}. Project saved.`,
|
||||
escProjPath,
|
||||
mirrorCtx
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
@ -1052,9 +1058,11 @@ export async function startMcpServer(config: ServerConfig): Promise<void> {
|
|||
['ensure_project_open', 'find_object_by_path']
|
||||
);
|
||||
const result = await executor.executeScript(script);
|
||||
return formatToolResponse(
|
||||
return await formatModifyingResponse(
|
||||
result,
|
||||
`Method '${args.methodName}' created under '${sanParentPath}' in ${args.projectFilePath}. Project saved.`
|
||||
`Method '${args.methodName}' created under '${sanParentPath}' in ${args.projectFilePath}. Project saved.`,
|
||||
escProjPath,
|
||||
mirrorCtx
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
@ -1219,9 +1227,11 @@ export async function startMcpServer(config: ServerConfig): Promise<void> {
|
|||
['ensure_project_open', 'find_object_by_path']
|
||||
);
|
||||
const result = await executor.executeScript(script);
|
||||
return formatToolResponse(
|
||||
return await formatModifyingResponse(
|
||||
result,
|
||||
`DUT '${args.name}' (${args.dutType}) created in '${sanParentPath}' of ${args.projectFilePath}. Project saved.`
|
||||
`DUT '${args.name}' (${args.dutType}) created in '${sanParentPath}' of ${args.projectFilePath}. Project saved.`,
|
||||
escProjPath,
|
||||
mirrorCtx
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
@ -1262,9 +1272,11 @@ export async function startMcpServer(config: ServerConfig): Promise<void> {
|
|||
['ensure_project_open', 'find_object_by_path']
|
||||
);
|
||||
const result = await executor.executeScript(script);
|
||||
return formatToolResponse(
|
||||
return await formatModifyingResponse(
|
||||
result,
|
||||
`GVL '${args.name}' created in '${sanParentPath}' of ${args.projectFilePath}. Project saved.`
|
||||
`GVL '${args.name}' created in '${sanParentPath}' of ${args.projectFilePath}. Project saved.`,
|
||||
escProjPath,
|
||||
mirrorCtx
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
@ -1290,9 +1302,11 @@ export async function startMcpServer(config: ServerConfig): Promise<void> {
|
|||
['ensure_project_open', 'find_object_by_path']
|
||||
);
|
||||
const result = await executor.executeScript(script);
|
||||
return formatToolResponse(
|
||||
return await formatModifyingResponse(
|
||||
result,
|
||||
`Folder '${args.folderName}' created in '${sanParentPath}' of ${args.projectFilePath}. Project saved.`
|
||||
`Folder '${args.folderName}' created in '${sanParentPath}' of ${args.projectFilePath}. Project saved.`,
|
||||
escProjPath,
|
||||
mirrorCtx
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
@ -1316,9 +1330,11 @@ export async function startMcpServer(config: ServerConfig): Promise<void> {
|
|||
['ensure_project_open', 'find_object_by_path']
|
||||
);
|
||||
const result = await executor.executeScript(script);
|
||||
return formatToolResponse(
|
||||
return await formatModifyingResponse(
|
||||
result,
|
||||
`Object '${sanObjPath}' deleted from ${args.projectFilePath}. Project saved.`
|
||||
`Object '${sanObjPath}' deleted from ${args.projectFilePath}. Project saved.`,
|
||||
escProjPath,
|
||||
mirrorCtx
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
@ -1344,9 +1360,11 @@ export async function startMcpServer(config: ServerConfig): Promise<void> {
|
|||
['ensure_project_open', 'find_object_by_path']
|
||||
);
|
||||
const result = await executor.executeScript(script);
|
||||
return formatToolResponse(
|
||||
return await formatModifyingResponse(
|
||||
result,
|
||||
`Object '${sanObjPath}' renamed to '${args.newName}' in ${args.projectFilePath}. Project saved.`
|
||||
`Object '${sanObjPath}' renamed to '${args.newName}' in ${args.projectFilePath}. Project saved.`,
|
||||
escProjPath,
|
||||
mirrorCtx
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
@ -1792,9 +1810,11 @@ export async function startMcpServer(config: ServerConfig): Promise<void> {
|
|||
['ensure_project_open']
|
||||
);
|
||||
const result = await executor.executeScript(script);
|
||||
return formatToolResponse(
|
||||
return await formatModifyingResponse(
|
||||
result,
|
||||
`Library '${args.libraryName}' added to ${args.projectFilePath}. Project saved.`
|
||||
`Library '${args.libraryName}' added to ${args.projectFilePath}. Project saved.`,
|
||||
escaped,
|
||||
mirrorCtx
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue