openworkid.org / mcp

MCP Server

upstand.work exposes a Model Context Protocol server. AI agents can read public profiles without auth, and perform write operations with user-delegated tokens. This page covers both paths: configuring a personal agent and building integrations.

MCP 2024-11-057 tools3 auth levelsREST fallback
Quickstart
01
Add the server to your agent config
Server URL: https://mcp.upstand.work/sse — public read tools work immediately with no token.
02
Generate a user token for write access
Go to upstand.work/settings/tokens → Generate MCP token. Valid 90 days, revocable anytime.
03
Pass the token as a header
Your agent sends Authorization: Bearer <token> on authenticated calls. No header needed for public tools.
Auth header formats
// User Auth — personal token
Authorization: Bearer oiw_usr_xxxxxxxxxxxxxxxxxxxxxxxx

// Client Auth — API key (M3)
Authorization: Bearer oiw_api_xxxxxxxxxxxxxxxxxxxxxxxx

// Public — no header needed

Auth Levels

Three distinct levels. Each call runs at exactly one level — they do not stack.

Public
No token required
Any agent reads public profiles and verifications. No registration.
get_profileget_verifications
User Auth
Magic-Link token
Pro delegates access to their own agent. Read + write on own profile only.
get_suggestionsget_market_benchmarkadd_experiencerequest_verification
Client Auth
API key (M3)
Businesses with an API key. Read-only on opt-in profiles only.
search_profiles

Tool Reference
Milestone 1 — Available now
get_profile(username)
PublicM1

Returns a complete ProfessionalIdentity document. Includes experience records, verification references, extensions, and human proof status. Withdrawn verifications are excluded.

Parameters
NameTypeReq
usernamestringrequired
include_extensionsbooleanoptional
format"full"|"summary"optional
Returns
FieldType
identityProfessionalIdentity
verification_countinteger
last_updatedISO 8601
Example response (summary)
{
  "identity": {
    "id": "upstand.work/thomas-weber",
    "name": "Thomas Weber",
    "summary": "Senior Finance Controller, 20 years automotive...",
    "humanProof": { "verified": true, "peerVerificationCount": 3 },
    "availableForWork": true
  },
  "verification_count": 3,
  "last_updated": "2026-04-10T14:00:00Z"
}
get_verifications(username)
PublicM1

Returns all active peer verifications. Withdrawn verifications are excluded. Mutual verifications appear with mutualFlag: true. Verifier email addresses are never returned — only the email domain.

Parameters
NameTypeReq
usernamestringrequired
experience_idstringoptional
include_one_clickbooleanoptional
Returns
FieldType
verificationsPeerVerification[]
totalinteger
mutual_countinteger
get_suggestions()
User AuthM1

AI-generated analysis of what is missing or weak in the authenticated user's profile. Returns missing extension fields, experiences with no verifications, and suggested verifiers.

Parameters
NameTypeReq
No parameters. Operates on the authenticated user's own profile.
Returns
FieldType
profile_strength"weak"|"moderate"|"strong"
missing_fieldsstring[]
unverified_experiencesstring[]
suggested_verifiersobject[]
Example response
{
  "profile_strength": "moderate",
  "missing_fields": ["extensions.finance-controller.rateRange", "summary"],
  "unverified_experiences": ["upstand.work/thomas-weber/exp/002"],
  "suggested_verifiers": [{
    "experience_id": "exp/002",
    "suggestion": "Someone from your BMW Group period has not yet verified this experience."
  }]
}
Milestone 2 — In development
get_market_benchmark(category, region?)
User AuthM2

Anonymised rate benchmarks for a given profession category. Data comes from verified profiles that have opted in.

Parameters
NameTypeReq
categorystringrequired
regionstringoptional
senioritystringoptional
unit"hour"|"day"optional
Returns
FieldType
p25 / p50 / p75number
currencystring
sample_sizeinteger
data_source"internal"|"seed"|"hybrid"
add_experience(experience)
User AuthM2

Creates a draft ExperienceRecord. The draft is returned for user review and must be confirmed before going live. AI writes the draft — the human confirms it.

Returns a draft, not a live record. The user must confirm via confirm_experience(draft_id) before it becomes public.
Parameters
NameTypeReq
experienceExperienceRecordrequired
Returns
FieldType
draft_idstring
draftExperienceRecord
confirm_urlURL
status"draft"
request_verification(experience_id, verifier)
User AuthM2

Sends a verification request email to a named verifier for a specific experience. Rate-limited to 10 per week.

Human-in-the-loop is required. Do not automate this call. The user must confirm who to contact and what context to include.
Parameters
NameTypeReq
experience_idstringrequired
verifier_emailstringrequired
verifier_namestringrequired
context_messagestringrequired
Returns
FieldType
request_idstring
sent_atISO 8601
weekly_remaininginteger
Milestone 3 — Planned
search_profiles(criteria)
Client AuthM3

Searches verified profiles matching criteria. Only returns profiles with availableForWork: true and API discovery enabled. Returns profile data only — no contact details.

Parameters
NameTypeReq
extension_idstringrequired
fieldsobjectoptional
min_verificationsintegeroptional
regionstringoptional
limitintegeroptional
Returns
FieldType
profilesProfessionalIdentity[]
totalinteger
api_credits_usedinteger

Integration Examples
claude_desktop_config.json
{
  "mcpServers": {
    "upstand-work": {
      "url": "https://mcp.upstand.work/sse",
      "headers": {
        // remove for read-only access
        "Authorization": "Bearer oiw_usr_your_token_here"
      }
    }
  }
}
Example conversation with Claude
You: "What's missing from my upstand.work profile?"

Claude: [calls get_suggestions()]
"Your Continental experience has no verifications yet.
 Would you like me to draft a request to Maria Hoffmann?"

You: "Yes — she was my CFO there."

Claude: [calls request_verification(experience_id, verifier, context)]
"Request sent. She'll receive an email she can respond
 to in 60 seconds — no account needed."
OpenAI Agents SDK — Python
from agents import Agent, MCPServerSse
from agents.mcp import MCPServerSseParams

server = MCPServerSse(
    params=MCPServerSseParams(
        url="https://mcp.upstand.work/sse",
        headers={ "Authorization": f"Bearer {TOKEN}" }
    ),
    cache_tools_list=True
)

agent = Agent(
    name="Profile Manager",
    instructions="Help the user manage their upstand.work profile.",
    mcp_servers=[server]
)

result = await Runner.run(agent, "What verifications am I missing?")
REST API — mirrors MCP tools exactly
# Get profile (public)
GET https://api.upstand.work/v1/profiles/{username}

# Get verifications (public)
GET https://api.upstand.work/v1/profiles/{username}/verifications

# Get suggestions (user auth)
GET https://api.upstand.work/v1/me/suggestions
Authorization: Bearer oiw_usr_your_token_here

# Request verification (user auth)
POST https://api.upstand.work/v1/me/verifications/request
Authorization: Bearer oiw_usr_your_token_here
Content-Type: application/json

{
  "experience_id": "exp/001",
  "verifier_email": "maria@continental.com",
  "verifier_name": "Maria Hoffmann",
  "context_message": "We worked together on the reporting project in 2021."
}

Rate Limits
Auth LevelScopeLimitWindow
Publicget_profile, get_verifications60 reqper minute / IP
User AuthAll read tools300 reqper hour / token
User Authrequest_verification10 reqper week / user
User Authadd_experience (drafts)20 reqper day / user
Client Authsearch_profilesQuota-basedper API plan

Every response includes X-RateLimit-Remaining and X-RateLimit-Reset headers.


Error Codes
400invalid_paramsRequired parameter missing or malformed.
401unauthorizedToken missing or expired. Generate a new one at upstand.work/settings/tokens.
403forbiddenToken exists but does not have permission for this tool’s auth level.
404not_foundProfile does not exist, is inactive, or has been deleted.
409verification_existsA pending request to this verifier for this experience already exists.
422profile_not_publicProfile exists but is unlisted or inactive. Public tools cannot access it.
429rate_limitedRate limit exceeded. Check X-RateLimit-Reset for when the window resets.
500server_errorServer-side error. Exponential backoff retries are safe for all read tools.
503unavailableTool not yet available in the current milestone.