portal-api
by AWfusion
README.md
# Portal.io API MCP
A local, read-only MCP server for a Portal.io account. It signs API requests with Portal's HMAC-SHA256 scheme and makes account data available to Codex through structured tools.
## Included tools
- `test_connection`: confirm the current credentials can make a read-only request.
- `list_proposals` and `get_proposal`: browse proposal summaries and details.
- `list_users`: look up Portal salesperson IDs.
- `search_contacts`: find contacts in the Portal account.
- `search_catalog`: search account catalog items when Catalog API access is enabled.
Version `0.1.1` contains no mutation tools. It cannot create, update, archive, or send anything in Portal.
## Install
```sh
git clone https://github.com/AWfusion/portal-api-mcp.git
cd portal-api-mcp
npm ci
cp .env.example .env
```
Fill in `.env` with credentials from the same Portal environment:
```env
PORTAL_ENV=sandbox
PORTAL_BASE_URL=https://sandbox.api.portal.io
PORTAL_APP_ID=your-api-application-key
PORTAL_SECRET_KEY=your-secret-key
PORTAL_USER_API_KEY=the-meta-apiKey-value-from-the-credential-exchange
PORTAL_WRITE_ENABLED=false
```
For production, use `PORTAL_ENV=production` and `PORTAL_BASE_URL=https://api.portal.io` only when Portal has issued and enabled production credentials for the integration.
`PORTAL_USER_API_KEY` must be the exact `meta.apiKey` returned by `GET /authenticate/apikeyexchange`. Do not substitute the application ID, secret key, a Portal UI token, or the username/password used for the one-time exchange. Portal's returned User API Key is Base64-encoded and is normally 44 characters long.
The actual `.env` file is ignored by Git. Keep its permissions owner-only:
```sh
chmod 600 .env
```
## Verify
```sh
npm test
npm run verify
```
`npm run verify` performs a local MCP initialization, confirms every tool is registered, and makes one read-only `GET /public/proposals?PageNumber=1&PageSize=1` call. It outputs no credentials.
## Register Globally in Codex
Run the included installer from the project directory:
```sh
./scripts/install-codex-mcp.sh
```
It registers this local process globally under the name `portal-api`. Confirm it with:
```sh
codex mcp get portal-api
```
Restart Codex or open a new task after registration so the tools are discovered. Typical requests include “list my most recently modified Portal proposals” and “search the catalog for Denon receivers.”
## Troubleshooting
- `app id could not be found`: the API application ID is not enabled for the selected base URL. Sandbox credentials belong at `https://sandbox.api.portal.io`; production credentials belong at `https://api.portal.io`.
- `request signature (hash) is invalid`: first confirm `PORTAL_USER_API_KEY` is the Base64 `meta.apiKey` returned by the credential exchange, then confirm the app ID, secret, and User API Key all came from the same environment.
- Catalog queries return authorization errors: ask Portal to enable Catalog API access for the account.
## Development
The server uses Node 20 or newer and has no database or hosted component. Request signing follows Portal's current API contract: GET signatures include the fully encoded request URL and omit the content type; the API secret is used as the raw ASCII HMAC key and is not Base64-decoded.
See [CHANGELOG.md](CHANGELOG.md) for release history and [BUILD-INFO.md](BUILD-INFO.md) for the release contract.
TDQS
A3.8/5.0
Scored across 6 tools
Disambiguation5/5
Each tool targets a distinct resource and action: proposals (get/list), users (list), catalog (search), contacts (search), and connection test. No overlap.
Naming Consistency5/5
All tool names follow a consistent verb_noun pattern in snake_case (e.g., get_proposal, list_users, search_catalog).
Tool Count5/5
6 tools is appropriate for a read-only API surface covering proposals, users, catalog, contacts, and connection verification.
Completeness4/5
Covers the main read operations for key entities, but lacks get_user or get_contact individually; however, this is reasonable for the scope.
Maintenance
ActivitySlowing
ResponsivenessNo issues