Share one implementation between CLI commands and MCP tools
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 35/100
- issue の種類
- リファクタリング
- 明瞭さ
- おおむね明確
- 活発さ
- 活発
- 技術スタック
- csharp
- 領域
- backend-api-design, cli, tooling
調査の方向性
AGENTS.md と Features/Mcp/McpHostCommand.cs の登録を読み、migration slice 1 に向けて LeaveUpdateService と Timesheet 更新 CLI および MCP アダプターを調査します。完了の条件は、アダプターが 1 つの共有サービスを使用し、アーキテクチャテストとパリティテストが委譲を強制し、確立済みの --json wire 形式が変更されないことです。
索引モデルが issue の本文から書いたものです。
説明
Why
47 MCP tools (18 default, 29 accounting-gated) are registered in Features/Mcp/McpHostCommand.cs. Only four share a service with their CLI counterpart (LeaveCreateService, LeaveUpdateService, LeaveBalanceImportService, WeekCoverageService). The other 43 re-implement the orchestration the CLI command already does, so every fix lands twice or, as with #21, only once. AGENTS.md already states the rule ("MCP delegates to the same service"); this issue makes the codebase follow it and adds a test that keeps it that way.
Inventory (where sharing is missing)
| MCP tool | CLI command | Today |
|---|---|---|
| GetTimesheets | ts get |
duplicate; MCP skips weekends, CLI does not |
| CreateTimesheet | ts create |
duplicate; CLI also resolves rate, category, deducted time |
| UpdateTimesheet | ts update |
duplicate, destructive (#21) |
| DeleteTimesheet / AcceptSuggestedTimesheet | ts delete / ts accept |
duplicate; empty-response handling differs |
| GetSuggestedTimesheets | ts suggest |
duplicate; note this refreshes server state, it is not read-only |
| CheckWeek | ts check |
shared service, duplicated projection |
| SearchClients / GetProjectsForClient / GetClientRate / GetCrmBookings / ListIterations | client search / project list / rate get / booking list / iteration list |
duplicate; missing-rate result differs |
| GetLeaveEntries / GetLeaveBalance / GetLeaveBalanceStatus | leave list / leave balance / leave balances status |
duplicate |
| All accounting tools (invoices, receipts, credit notes, products, rates, unbilled, recurring, query, summary, prepaid) | matching tp commands |
duplicate; prepaid calculation lives in TimeProApiClient |
| GetInvoicesByClient, GetUnpaidInvoicesByClient, ListCategories, ListBillableTypes, ListAllSkus | none | MCP-only, violates the "CLI first" rule |
| none | leave cancel |
CLI-only |
Target architecture
- Per feature:
Services/with a request record, result record and a service that owns validation, defaults, lookups, read-merge and API orchestration. No single giant service. - CLI command = parse settings, build request, call service, render table or JSON, choose exit code.
- MCP tool = bind args, build the same request, call the same service, serialize the same result record. Never shell out to
tp. - One result type feeds both
--jsonand MCP structured content. One serializer policy (OutputHelperomits nulls and stringifies enums; MCP classes currently differ). - One application error type (category, nullable API status, safe message, recovery hint,
mayHaveBeenApplied). CLI maps it to the{"error":{...}}envelope plus exit code; MCP maps it toCallToolResult.IsError = true. Today MCP returns{"error":"..."}strings that look like successful results. - Writes with previews follow the
LeaveUpdateServiceshape:PrepareAsync(no writes) thenApplyAsync. CLI--dry-runand MCPdryRuncall the same preparation. - Adapter-only: prompts,
--yes, table formatting, file vs base64 output, exit codes. MCP confirmations use client approval or elicitation; a model-suppliedconfirmed=trueis not consent.
Enforcement
- Architecture test: no
ITimeProApiClient,HttpClient, or console access fromFeatures/Mcp/Tools. Reflection can check dependencies; use Roslyn or IL inspection if delegation itself must be proven. - Every
[McpServerTool]maps to a shared service and a registered CLI command, with a temporary allowlist for unmigrated tools that may only shrink. - Adapter parity tests against the same fake service; snapshot
tools/listnames, schemas and annotations.
Migration order
| # | Slice | Size |
|---|---|---|
| 1 | TimesheetUpdateService, both update adapters (fixes #21; also home for #22 --iteration) |
M |
| 2 | Timesheet create (shared rate/category/location logic; no implicit MCP writes) | L |
| 3 | Delete, accept, and normalising leave/import outcomes | M |
| 4 | Timesheet reads, suggestions, week coverage (explicit weekend policy) | M |
| 5 | Prepaid and accounting reads (move prepaid maths out of TimeProApiClient) |
M each |
| 6 | Lookups and the MCP-only / CLI-only gaps above | S each |
| 7 | Remove allowlist and legacy projections | S |
Do not change established --json wire shapes while extracting; schema changes are separate, explicit PRs. Do this before the SDK upgrade (#39).
- 主要言語
- C#
- スター
- 3
- フォーク
- 0
- 平均マージ
- 8分
- マージ済み PR(30日)
- 26
環境構築
このプロジェクトの開発コンテナを、あなたの GitHub アカウントでブラウザ上に起動します。
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドなし
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
SSWConsulting/TimePro.Tools のほかの issue
-
Priority: P3 Type: Refactor
難易度 5/5 1週間以上 初心者へのやさしさ 38/100
SSWConsulting/TimePro.Tools#101 ·
メンテナーはふだん 1 日以内に返信
-
Priority: P3 Type: Refactor
難易度 4/5 3〜5日 初心者へのやさしさ 42/100
SSWConsulting/TimePro.Tools#100 ·
メンテナーはふだん 1 日以内に返信
-
Accounting: share product, SKU, rate, unbilled and recurring reads (unbilled paging is a no-op)オープンPriority: P3 Type: Refactor
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
SSWConsulting/TimePro.Tools#99 ·
メンテナーはふだん 1 日以内に返信
-
Priority: P2 Type: Refactor
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
SSWConsulting/TimePro.Tools#98 ·
メンテナーはふだん 1 日以内に返信
-
Priority: P2 Type: Bug Type: Refactor
難易度 5/5 1週間以上 初心者へのやさしさ 38/100
SSWConsulting/TimePro.Tools#97 ·
メンテナーはふだん 1 日以内に返信
SSWConsulting/TimePro.Tools の issue をすべて見る
似ている issue
-
bug priority: P2
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
:watch: Not Triaged dotnet-csharp/svc fundamentals/subsvc
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
メンテナーはふだん 1 日以内に返信
-
Wrong values of Kernel32.FileShare.Delete and Kernel32.FileAttributes.PosixSemantics対応中かも @ElectLive が今日担当しました。 オープンbug good first issue help wanted
難易度 1/5 1時間未満 初心者へのやさしさ 83/100
ForNeVeR/TruePath#241 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 66/100
files-community/Files#19047 ·
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信