mcp-server-productive
mcp-server-productive
Productive.io API v2 用のMCPサーバー — 1つの組織を対象としたプロジェクト、タスク、タイムトラッキング、リソースプランニング、財務、CRM、レポート。
Productiveは132のリソースに対して約650のオペレーションを公開しています。これらを650のMCPツールに変換すると、クライアントのツールリストが溢れてしまうため、このサーバーは生成されたレジストリによって駆動される12のツールで構成されています。ツールは汎用的で、レジストリが各リソースが実際に受け付ける内容を把握しています。
ツール
ディスカバリ — productive_search_capabilities、productive_describe_resource、productive_check_connection、productive_describe_custom_fields
読み取り — productive_list(フィルタ、ソート、インクルード、ページング、およびグループ化を伴う26のレポートエンドポイント)、productive_get
書き込み — productive_create、productive_update、productive_delete、productive_run_action(150の名前付き動詞: archive、restore、approve、close、copy、finalize、send…)、productive_track_time、productive_commit_operation
ユーザーごとの認証(オプトイン) — productive_connect、productive_status、productive_disconnect — 認証を参照
まず productive_search_capabilities から始めてください。Productiveのリソース名は独自のものです。予算は deal、ボードの列は workflow_status、タイムシートの承認は time_entries に存在します。推測はAPI呼び出しのコストがかかります。
Related MCP server: productive-mcp-rb2
レジストリ
src/productive/registry.generated.ts は、Productiveが公開しているOpenAPIドキュメントから scripts/generate-registry.mjs によって生成され、コミットされています。そのためCIはネットワークを必要とせず、仕様の変更はレビュー可能な差分として現れます。このレジストリは、すべてのリソースについて、フィルタフィールド、ソートキー、レポートのグループキー、インクルード可能なリレーションシップ、作成・更新用の書き込み可能な属性(必須のものをマーク付きで)、および各名前付きアクションを記録しています。
これこそが、12のツールが誠実であり続けるための仕組みです。productive_describe_resource は1つのリソースの正確な契約を返し、すべての引数はリクエストを送信する前にその契約と照合されます。
npm run registry:generate で再生成します(ローカルコピーの仕様を使うにはパス引数を追加します)。手書きの分類(リスク階層、外部向けフラグ、ブロックされたオペレーション)が仕様内のどのパスとも一致しなくなった場合、ジェネレータはビルドを失敗させます。これにより、上流でのリネームがガードを静かに失わせることはありません。
実測に基づくAPIの動作
ここに記載されている内容はすべて、実際の組織に対して検証済みです。仕様とAPIは、重要な点で食い違うことがあるからです。
時間は分単位。金額は最小通貨単位。 時間エントリの 2 は2分を意味します。レスポンスも同様の単位で返ってきます。
不明なフィルタ、ソート、インクルードは明確に失敗します。 HTTP 400とともに unsupported_filter、sort_param_unsupported、unsupported_include が返ります。したがって、ここでそれらを検証することは、セーフティネットではなく、より良いエラーを返すためのものです。
不明な書き込み属性は静かに失敗します。 スペルミスのある属性での PATCH はHTTP 200を返し、何も変更しません — 成功と区別がつきません。そのため、このサーバーは、リソースが宣言していない属性を拒否し、実際には行われなかった書き込みを報告することを避けます。これはレジストリが行う最も有用なことです。
すべてのフィールドに、ちょうど6つのフィルタ演算子があります: contains、eq、gt、lt、not_contain、not_eq。仕様はフィールドごとに4つを記載しており、実際に動作する gt/lt を省略しています。gte、lte、in、not_in、starts_with、ends_with、blank、present はすべて unsupported_filter_operation で拒否されます。包含的な比較は存在しないため、包含的な範囲を指定するには、リソース独自の after/before または <field>_after/<field>_before フィルタフィールドが必要です。
page[size] は200で上限となり、静かにクランプされます。 500を要求すると、エラーなしで200が返ります。結果には total と nextPage が含まれるため、1ページを全体の回答と誤認することはありません。
PATCHは本当に部分更新です。 省略された属性は値を保持します。レコード全体を再送信する必要はありません。
data.type はチェックされません。 type: "projects" でタスクをパッチすると成功し、変更が適用されます。このサーバーはそれでも正しいタイプを送信します。
組織IDが「指定される必要がある」という403は、欠落ではなく誤りを意味する場合があります。 同じ no_organization_id コードが、ヘッダーの欠落と、トークンが到達できない組織の両方をカバーしています。
存在しない機能は403ではなく404で応答します。 /boards は、それを持たない組織では404を返します。これは壊れたパスのように見えます。
削除は復元できる場合があります。 削除されたタスクは deleted_items に item_type と item_id とともに現れ、そのリソースの restore アクションを通じて復元できます。タスクについてのみ検証済みです — すべてのタイプに当てはまるとは想定しないでください。
GET /users は唯一の呼び出し元スコープのエンドポイントです。 これは正確に1つのレコード — あなた自身 — を返し、このサーバーがトークンの所有者を識別する方法です。/users/me は存在せず、そのパスは404を返します。/organization_memberships に注意してください: これは固定された組織にスコープされておらず、呼び出し元が所属するすべての組織にわたるメンバーシップを一覧表示するため、その行数は人数ではありません。
レート制限ヘッダーはありません。 あるのは x-request-id のみで、このサーバーのエラーはそれを引用します。制限を探るのではなく、429でバックオフしてください。
権限
4つのスイッチがあり、すべてデフォルトでオフです。読み取り専用サーバーが、有用で安全なデフォルトです。
スイッチ | 対象 |
| マスタースイッチ。これがない限り、何も変更されません。 |
| 金銭、価格設定、給与、顧客が受け取る文書: 請求書、ラインアイテム、支払い、請求、経費、発注書、提案書、契約書、価格、レートカード、給与、諸経費、税率、銀行口座、子会社。 |
| アクセスと組織全体の設定: 人、メンバーシップ、権限セット、チーム、招待、カスタムフィールド、ウェブフック、統合、承認およびタイムトラッキングポリシー。 |
| ティアゲートに加えて削除。 |
Productiveにはマスタースイッチ1つでは不十分です。同じAPIがタスクの移動、請求書の発行、権限セットの付与を行い、これらは3つの異なる判断です。プロジェクト作業の実行を信頼されたサーバーが、それによって請求書を送信できるようになってはいけません。
PRODUCTIVE_ALLOWED_RESOURCES / PRODUCTIVE_DENIED_RESOURCES はインスタンスをさらに絞り込み、読み取りにも適用されます — タイムトラッキングにスコープされたインスタンスは、給与も読み取るべきではありません。
スイッチに関係なく、決して公開されません: passwords、sessions、organization_subscriptions、認証不要の public/* 共有リンク、および PATCH /users/{id}/update_password。これらはゲートされるのではなくレジストリに存在しないため、ポリシーのバグによって再び公開されることはありません。
2段階書き込み
通常のプロジェクト作業 — タスク、時間エントリ、予約、コメント — は1回の呼び出しで書き込まれます。すべての時間エントリにハンドシェイクを要求すると、人々が最も頻繁に行う操作に対してサーバーが使えなくなってしまいます。
影響範囲が広いものはすべてステージングされます: ツールは正確なリクエストとハッシュを返し、何も送信しません。productive_commit_operation は、オペレーションが変更されずに戻ってきた場合にのみ実行します。これには、財務および管理ティア、すべての削除、組織外に出るもの、およびすべての bulk_* アクションが含まれます — これらはフィルタが一致するすべてのレコードに作用するため、明示的なフィルタなしでは実行を拒否します。
6つのオペレーションは、実行された瞬間に組織外の誰かに届くため、outward としてフラグ付けされています: invoices.send、invoices.send_einvoice、people.invite、people.resend、organizations.resend_code、および invitation の作成。
認証
2つのモードがあります。PRODUCTIVE_ORGANIZATION_ID は両方で必須であり、ツールの引数になることはありません。
ユーザーごとのトークン(推奨)
各人は自分自身の Productiveトークンをリンクするため、Productiveはその人の権限を適用し、その人が行った操作にその人の名前を記録します。
これは、ほとんどのシステムよりもProductiveで重要です。Productiveは作業を人に帰属させます: 時間エントリは person_id に属し、すべての変更はアクティビティログにトークンの所有者として記録されます — これはクライアントへの請求書を裏付ける記録です。共有トークン1つでは、そのログはサービスアカウントがすべてを行ったと記録されます。
PRODUCTIVE_PER_USER_AUTH=true
PRODUCTIVE_TRUST_FORWARDED_USER=true
PRODUCTIVE_ENCRYPTION_KEY=<min 16 chars>
PRODUCTIVE_STORE_PATH=/data/store.json
PRODUCTIVE_PUBLIC_BASE_URL=https://productive.example.com
# PRODUCTIVE_API_TOKEN deliberately unsetフロー:
呼び出し元は
productive_connectを実行し、10分間有効な単回使用リンクを取得します。これはその人のアイデンティティに紐付けられています。そのリンクを開き、Productiveの設定 → API連携で作成したトークンを貼り付けます。トークンはブラウザからサーバーに直接送信されるため、会話のトランスクリプトに入ることはありません — Productiveトークンはアカウント全体と同等のベアラー権限を持ち、後述の測定結果のとおり、通常は複数の組織に到達できます。
保存する前に、サーバーはそのトークンとこの組織のIDを使って
GET /usersを呼び出します。この1回の呼び出しで3つのことが証明されます: トークンが有効であること、この組織に到達できること、そして誰のものかということ。その後、ページはどのアカウントがリンクされたかを確認します。トークンはAES-256-GCMで保存時に暗号化され、検証済みのアイデンティティごとに1行ずつ保存されます。
注意すべき点:
アイデンティティはゲートウェイからのみ取得されます。
X-MCP-UserはPRODUCTIVE_TRUST_FORWARDED_USER=trueの場合にのみ読み取られ、MCPクライアントが制御するものからは決して読み取られません。検証済みトークンからヘッダーを設定し、クライアントが提供したコピーを除去するゲートウェイの背後でのみ有効にしてください — そうしないと、呼び出し元が任意のアイデンティティを名乗ってその人として行動できてしまいます。フォールバックはありません。 未登録の呼び出し元は
NOT_CONNECTEDを受け取り、たとえPRODUCTIVE_API_TOKENが設定されていても共有トークンは受け取りません。フォールバックがあると、借り物の権限を渡すことになり、このモードが排除するために存在する失敗を招きます。/productive/enrollはユーザーのブラウザから到達可能である必要があります。MCPゲートウェイを経由せずに — ブラウザはゲートウェイのベアラートークンを保持できないためです。PRODUCTIVE_PUBLIC_BASE_URL上の/productive/*をコンテナに直接ルーティングしてください。そのセキュリティは、単回使用でアイデンティティに紐付けられたステートトークンです。PRODUCTIVE_STORE_PATHをボリューム上に永続化し、PRODUCTIVE_ENCRYPTION_KEYを安定に保ってください — 変更すると、保存されているすべてのトークンが復号不可能になります。トークン自体のProductiveメールが呼び出し元のディレクトリアドレスと異なる場合、それはページと
productive_statusで明確に報告され、それでも接続されます。代わりに拒否するにはPRODUCTIVE_REQUIRE_EMAIL_MATCH=trueを設定してください。デフォルトでオフなのは、他人のトークンを貼り付ける人はすでにそれを保持しているため、拒否してもセキュリティ上の利得はほとんどなく、一方で別のアドレスでのProductiveアカウントは十分にあり得るからです。ユーザーごとの認証は、組織ではなく、権限と帰属を分離します。組織の固定は依然として全員に適用されます。
共有トークン
PRODUCTIVE_API_TOKEN に1つのトークンを設定します。シンプルで、stdioや単一のオペレーターに適しています — ただし、すべての呼び出し元はそのトークンの所有者として、その権限で動作し、Productiveのアクティビティログはすべての変更をその人に帰属させます。
PRODUCTIVE_TRUST_FORWARDED_USER はここでも役立ちます。人物に関連する書き込み(タイムエントリー、予約)は、デフォルトでトークンの所有者ではなく解決された呼び出し元に帰属し、アドレスが誰にも一致しない場合や複数の人物に一致する場合、サーバーは推測することを拒否します。productive_check_connection はどちらの場合でもトークンの所有者を明示するため、帰属先が驚きになることはありません。
複数組織
1つのインスタンスは正確に1つの組織にのみサービスを提供します。X-Organization-Id は環境から取得され、ツールの引数になることはないため、汎用ツールを含むいかなるコードパスも別のテナントに到達できません。2つ目の組織には2つ目のインスタンスを実行してください。イメージは同じです。
これは理論上の話ではありません。1つのトークンが日常的に複数の組織に到達します。この開発に使用したアカウントでは、GET /organizations は3つの組織を返し、ヘッダーを切り替えるだけで組織間を移動できました(他の2つは「見つからない」ではなく 403 subscription_expired を返しました)。ヘッダーが境界のすべてであり、それが引数として渡されるのではなく固定される理由であり、登録済みのユーザー別トークンが保存前に この 組織に対して検証される理由でもあります。
設定
.env.example を参照してください。必要な変数は2つです。PRODUCTIVE_API_TOKEN(Productive の設定 → API連携。作成ユーザーの権限を継承します)と PRODUCTIVE_ORGANIZATION_ID(Productive URL 内の数値 ID)です。
PRODUCTIVE_AUDIT_LOG を設定すると、ミューテーション試行ごとに1行の JSON が追記されます。ポリシーが拒否した試行も含みます。リクエストボディは意図的に記録されません。それらには給与、レート、個人データが含まれており、ソースシステムと同程度に厳重に保護しなければならない監査証跡は、そもそも読まれない傾向にあるからです。
実行
npm install
npm run dev # stdio
npm run dev:http # streamable HTTP on :3000/mcp (stateless), /healthz open
npm test
npm run smoke:live # reads a real organization; stages one write, commits nothingDocker イメージ: ghcr.io/borgels/mcp-server-productive(main へのプッシュ時に公開)
ライセンス
Apache-2.0.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityAmaintenanceA Model Context Protocol (MCP) server for accessing Productive.io API endpoints (projects, tasks, comments, todos), tailored for read-only operations, providing streamlined access to essential data while minimizing token consumption18MIT
- AlicenseAqualityDmaintenanceEnables interaction with Productive.io for task management, time tracking, budget monitoring, and project overview through natural language.8358ISC
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with a Productive.io workspace for managing projects, tasks, time entries, budgets, and invoices through natural language.
- AlicenseNot gradedqualityDmaintenanceEnables interaction with Productive.io task management platform, allowing users to retrieve tasks and filter by assignee, status, or project.32ISC
Related MCP Connectors
ClickUp MCP — wraps the ClickUp REST API v2 (BYO API key)
Product Hunt MCP — wraps the Product Hunt GraphQL API v2 (api.producthunt.com)
Direct access to your Sanity projects (content, datasets, releases, schemas) and agent rules
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/borgels/mcp-server-productive'
If you have feedback or need assistance with the MCP directory API, please join our Discord server