Metadata-Version: 2.5
Name: marketing-data-platform
Version: 0.1.2
Summary: Remote-only OAuth MCP server and login CLI for the Data Platform API.
Requires-Python: >=3.11
Requires-Dist: httpx>=0.27.0
Requires-Dist: mcp<1.29.0,>=1.28.0
Requires-Dist: pydantic-settings>=2.6.0
Requires-Dist: pyjwt>=2.9.0
Description-Content-Type: text/markdown

# Data Platform Remote MCP

Remote-only MCP server for Data Platform API access.

The package exposes two commands:

- `data-platform-mcp-http`: run the stateless streamable HTTP MCP server.
- `data-platform-login`: complete Google login through the Data Platform
  authorization server and save rotating OAuth credentials.

Local stdio transport, fixed bearer headers, and
`~/.config/data-platform/mcp.env` are not supported. `data-platform-login`
does not send a loopback `redirect_uri` to Google. It registers a loopback
client with the API, opens `/authorize`, and lets the API use the Cloud Run
Google callback.

## Architecture

```text
Codex / MCP client
  -> OAuth 2.1 authorization code + PKCE
  -> Data Platform API authorization server
  -> short-lived MCP access token + rotating refresh token
  -> Remote MCP on Cloud Run
  -> short-lived delegated API token
  -> Data Platform API
  -> BigQuery / provider APIs
```

The MCP server does not connect to BigQuery directly. The Data Platform API owns
BigQuery credentials, tenant access control, and operation authorization.

The incoming MCP access token is never forwarded to the Data Platform API.
After validation, the MCP server mints a five-minute delegated token with the API
as its audience and the authenticated user as its subject. That delegated token
contains only the single scope needed by the current API operation.

## Codex configuration

Run the repository helper once. It prefers the current Codex Desktop bundled
CLI, registers the deployed streamable HTTP URL when needed, and starts OAuth:

```bash
./scripts/setup-data-platform-mcp
```

If a saved refresh-token family has been revoked, reset only this MCP login and
reauthorize with one command:

```bash
./scripts/setup-data-platform-mcp --reset
```

To re-login from a terminal without Codex, run the package login CLI against
the same API. Google still redirects to the Cloud Run callback. This works
from any directory; `uv run --package` does not, because it needs the repo
`pyproject.toml`.

```bash
uvx --from "git+https://github.com/KANEKIOU/data-platform.git#subdirectory=packages/data-platform-agent-tools" \
  data-platform-login \
  --api-base-url https://data-platform-api-exsmr2w2ba-an.a.run.app
```

From a local checkout of this repository:

```bash
cd /path/to/data-platform
uv run --package marketing-data-platform data-platform-login \
  --api-base-url https://data-platform-api-exsmr2w2ba-an.a.run.app
```

No `uv`, `uvx`, local MCP process, or manual `config.toml` edit is required.

Codex discovers the authorization server from protected-resource metadata,
performs authorization code + PKCE, and stores OAuth credentials in its configured
credential store. Access-token renewal uses the rotating refresh token; no bearer
token is copied into `config.toml`.

## Run the HTTP server

```bash
DATA_PLATFORM_API_BASE_URL=http://127.0.0.1:8002 \
DATA_PLATFORM_OAUTH_ISSUER_URL=http://127.0.0.1:8002 \
DATA_PLATFORM_MCP_RESOURCE_URL=http://127.0.0.1:8080/mcp \
DATA_PLATFORM_API_SESSION_SECRET=development-secret \
PORT=8080 \
uv run --package marketing-data-platform data-platform-mcp-http
```

Production runs the same command from the package Dockerfile on Cloud Run.

## MCP tools

- `get_daily_project_performance`（媒体実績とCATS成果を商材単位で返す）
- `get_daily_campaign_performance`（媒体実績と一意に解決できたCATS成果をcampaign単位で返す）
- `get_daily_cats_performance`（CATS成果と紐付いた媒体campaignをCATS広告名粒度で返す）
- `get_daily_performance`（媒体実績とCATS実績を粒度別の配列で返す）
- `get_daily_ad_performance`
- `get_daily_article_performance`
- `run_ad_operation`
- `list_operation_requests`
- `list_media_accounts`
- `list_submission_templates`
- `list_media_assets`
- `list_ad_assets`（広告と現在観測された静止画を`v_ad_assets`から取得）
- `get_line_yahoo_display_submission_spec`
- `build_line_yahoo_display_submission_payload`
- `create_line_yahoo_display_submission_request`
- `create_submission_request`
- `get_submission_request`
- `list_submission_requests`
- `prepare_submission_request`
- `create_action_plan`
- `get_action_plan`
- `list_action_requests`
- `prepare_action_plan`
- `open_campaign_action_review`
- `open_ad_action_review`
- `open_ad_group_action_review`（Google広告グループの個別Target CPA）

The destructive tools `approve_submission_request_from_app`,
`submit_submission_request_from_app`, `approve_action_plan_from_app`, and
`execute_action_plan_from_app` are registered with MCP Apps
metadata `ui.visibility=["app"]`. A conforming host keeps them out of the model's
tool surface and only proxies calls made by the connected App. Those calls use
`actor_type=mcp_app_delegation` and `app_id=action-cockpit-ui` when delegating to
the API's app-only routes.

Action-plan tools are thin clients for the `/api/action` ad-ops next-action
workflow (campaign/ad pause-resume, target CPA changes). `create_action_plan`
only drafts a plan and `prepare_action_plan` only dry-run validates it. Analysis
that uses a performance period should pass `performance_start_date` and
`performance_end_date`; the review App uses that same period for campaign-grain
CATS CV/mCV. The
model-visible `open_*_action_review` tools attach the matching self-contained
MCP App resource. Approval returns a short-lived confirmation receipt; execution
accepts that receipt rather than a model-supplied plan ID.

The packaged resources live in
`src/data_platform_agent_tools/ui_dist/{campaign,ad}.html`. They are generated by
the `apps/action-cockpit-ui` build and must be refreshed before publishing the
Python wheel or Cloud Run image whenever the UI changes.

Action Cockpit needs OAuth authentication but no operation scope. The model can
create and prepare action plans without one, while approval and execution remain
App-only. Those operations require the `mcp_app_delegation` actor plus a
single-use human-confirmation receipt.

## OAuth scopes

| Scope | Access |
| --- | --- |
| `submission:write` | Build, create, and dry-run prepare submission data |

MCP initialization and tool discovery require a valid access token but do not
require an operation scope. The authorization server issues no operation scope
by default. Request the submission scope only when the agent should prepare an
ad submission:

```bash
codex mcp login data-platform-mart --scopes submission:write
```

The Remote MCP checks the scope required by the selected tool before minting a
delegated API token. The Data Platform API checks the same scope again at the
route boundary. An authenticated token without this scope can still use read and
action-plan tools, while submission creation and preparation fail with an
insufficient-scope error. Final submission is protected by the App identity and
human-confirmation receipt instead of an OAuth operation scope.

## Environment variables

| Name | Required | Description |
| --- | --- | --- |
| `DATA_PLATFORM_API_BASE_URL` | yes | Data Platform API audience and base URL |
| `DATA_PLATFORM_OAUTH_ISSUER_URL` | yes | OAuth authorization-server issuer |
| `DATA_PLATFORM_MCP_RESOURCE_URL` | yes | Public MCP resource URL ending in `/mcp` |
| `DATA_PLATFORM_API_SESSION_SECRET` | yes | Shared signing secret for OAuth and delegated JWTs |
| `DATA_PLATFORM_MCP_DEFAULT_LIMIT` | no | Default row limit; default `100` |
| `DATA_PLATFORM_MCP_MAX_LIMIT` | no | Maximum row limit; default `1000` |
| `PORT` | no | HTTP listen port; default `8080` |

`DATA_PLATFORM_API_SESSION_SECRET` must be supplied through a managed secret in
production. Do not place it in source control or a client configuration.
