Setting up a GoMeddo MCP server

A Salesforce hosted MCP server lets an AI assistant such as Claude call GoMeddo automation directly against your org, so someone can ask "which rooms are free tomorrow between 10 and 11?" in plain language and get an answer produced by GoMeddo's own availability logic rather than by reading raw Reservation records. This guide covers the configuration an admin does once per org.

This is not a GoMeddo feature and there is nothing to install for it. It combines a standard Salesforce platform capability, hosted MCP servers, with the Flows and Apex actions that ship in the GoMeddo Agentforce package. You decide which GoMeddo actions an assistant can reach, and Salesforce hosts the endpoint and enforces your existing security model. No Agentforce license is needed.

Before you start, you need:

  • An org on Enterprise, Unlimited, Performance, or Developer Edition, in Lightning Experience, with hosted MCP servers available. If MCP Servers does not appear under API Catalog in Setup, the feature is not available in your org.

  • System Administrator access, including permission to create External Client Apps and view their consumer details.

  • GoMeddo and the GoMeddo Agentforce package installed. See Install the latest version.

  • An MCP client that supports custom connectors. For Claude this means a Pro, Max, Team, or Enterprise plan.

How it works

Three things make up a working setup, and they are configured in this order.

  1. An External Client App, which is how the assistant authenticates against your org.

  2. An MCP server definition, which is the endpoint the assistant connects to.

  3. One tool per GoMeddo action you want to expose.

Each tool maps one to one onto automation that already exists in your org, usually an autolaunched Flow and sometimes an Apex action. Nothing about that automation changes, so every availability rule, conflict rule, and validation it already applies keeps applying through the tool. The assistant is not reasoning about your booking rules, it is asking GoMeddo and reporting the answer.

Because Salesforce handles authentication, each user connects as themselves and reaches only the data their profile and permission sets already allow. No GoMeddo data is copied anywhere.

Which GoMeddo actions you can expose

The GoMeddo Agentforce package ships three actions that work well as tools. The first two are autolaunched Flows, the third is an Apex action.

API name

What it does

GMCopilot__Get_Occupancy_For_Agentforce

Returns the occupancy percentage per Resource over a date and time range.

GMCopilot__Generate_Possible_Timeslots_From_Agentforce

Returns candidate booking slots of a given duration, respecting GoMeddo availability rules.

GMCopilot__AgentforceReservationCreator

Creates a Reservation. See Create reservations for the input it expects.

You can expose any other active autolaunched Flow the same way, including Flows you build yourself, so the tool set is a choice rather than a fixed list.

Flows with a process type of PromptFlow are not eligible. Some of these appear in the Setup list and look usable, then fail when the tool is called, so check the process type before you add one.

Create the External Client App

The MCP endpoint is served from a Salesforce API gateway rather than from your org directly, so it needs an OAuth app of its own. This step cannot be scripted and takes about five minutes.

  1. In Setup, use the Quick Find box to open External Client App Manager.

  2. Click New External Client App.

  3. Enter a name such as Claude MCP and a contact email.

  4. Enable API (Enable OAuth Settings).

  5. In Callback URL, enter the callback your client uses, one per line. For claude.ai this is https://claude.ai/api/mcp/auth_callback, and Claude Code also uses http://localhost:8020/callback. These are hosted by the client vendor, so you do not host anything yourself.

  6. Under Selected OAuth Scopes, add Access MCP servers (mcp_api) and Perform requests at any time (refresh_token, offline_access).

  7. Enable Issue JSON Web Token (JWT)-based access tokens for named users.

  8. On the Policies tab, set Permitted Users to All users may self-authorize and enable Relax IP restrictions.

  9. Go to Settings > OAuth > Manage Consumer Details, complete the identity verification, and copy the consumer key and consumer secret.

Keep the consumer key and secret somewhere safe. You need both when you connect the client.

Step 7 is not optional and is the most common cause of a connection that fails later. Without it Salesforce issues a token the gateway cannot validate, and the client reports 401 Invalid token, which reads like a permissions problem and is not one.

Create the MCP server

  1. In Setup, use the Quick Find box to open API Catalog, then select MCP Servers.

  2. Click Create Salesforce MCP Server.

  3. Enter a label, a name, and a description. The description tells an assistant what this server is for, so write it for a reader who knows nothing about your org, for example GoMeddo availability, occupancy, and booking tools.

  4. Click Create.

The server now exists but is inactive and has no tools. You can change the label and the description later, but not the name, and the name determines the endpoint URL, so pick it deliberately.

Add GoMeddo tools and activate the server

A server can only be changed while it is inactive, so deactivate it first if you come back to it later.

  1. In Setup, open API Catalog > MCP Servers and select the Salesforce tab.

  2. Select your server.

  3. Click Add Server Assets, then Add Tools.

  4. Select the list view that holds flows, then find the GoMeddo Flow you want to expose.

  5. Click Add Tool next to it. The control changes to Added.

  6. Repeat for each Flow, then click Save.

  7. Open the Tools tab, select the annotations for each tool, and click Save. For the two Flows, select Read-only and Idempotent.

  8. Click Activate.

The server detail page now shows the endpoint URL, which takes the form https://api.salesforce.com/platform/mcp/v1/custom/<name> in production and https://api.salesforce.com/platform/mcp/v1/sandbox/custom/<name> in a sandbox, where <name> is the server name from the previous section. Copy it.

Annotations tell the client whether calling a tool is safe. Marking a read-only tool correctly is what stops the assistant asking the user to confirm every question.

Connect an MCP client

The protocol is open, so any MCP client works. These steps use Claude as the example.

  1. In claude.ai, go to Settings > Connectors.

  2. Click Add custom connector.

  3. Fill in the fields below and save.

  4. Click Connect and sign in to Salesforce when prompted, then approve the access request.

Field

Value

Name

A label your users will recognize, for example GoMeddo Booking Tools.

Remote MCP server URL

The endpoint URL from the previous section.

OAuth Client ID

The consumer key from the External Client App.

OAuth Client Secret

The consumer secret from the External Client App.

Each user connects with their own Salesforce login, so what an assistant can see and do is whatever that user can already see and do in GoMeddo.

A newly created External Client App can take up to 30 minutes to propagate. An invalid_client error shortly after you create it usually means propagation is still in progress rather than a wrong value.

Example tool configuration

A tool description is the only thing an assistant has to decide whether a tool fits the question, so it deserves more care than a Flow label. Write both the purpose and the selection criteria, and state the expected input formats, because the generated tool schema types every input as a plain string and a client that has to guess will get it wrong. Descriptions are capped at 1024 characters.

The two descriptions below are a working starting point for the packaged GoMeddo Flows. The reservation tool has its own description in the next section.

Occupancy

Backed by GMCopilot__Get_Occupancy_For_Agentforce. Annotate as read-only and idempotent.

Returns the occupancy percentage per bookable resource (meeting rooms, event spaces, desks, tables) over a date and time range. Use when asked how busy, full, or free spaces are, or for utilization reporting. Set dimensionId to scope the answer to a single resource, or omit it to get every resource. FORMATS: startOfRange and endOfRange are datetimes and must be written as YYYY-MM-DDTHH:mm:ss.SSSZ, for example 2026-08-28T08:00:00.000Z. The milliseconds and the trailing Z are both required.

Possible timeslots

Backed by GMCopilot__Generate_Possible_Timeslots_From_Agentforce. Annotate as read-only and idempotent.

Generates candidate booking timeslots of a given duration within a date and time range, respecting GoMeddo availability rules. Use when asked to propose or suggest possible times, rather than to check one specific slot. FORMATS: startDateTime and endDateTime are datetimes written as YYYY-MM-DDTHH:mm:ss.SSSZ, for example 2026-08-28T09:00:00.000Z. agentforceDuration and agentforceInterval are numbers of minutes.

Avoid exposing two tools that take the same inputs and answer the same question. When two tools look interchangeable, the assistant picks between them unreliably, and the fix is to expose one tool per distinct question.

Create reservations

The Apex action GMCopilot__AgentforceReservationCreator creates a Reservation through the same automation as the booking form. Conflict rules and validations apply, the record appears in the calendar, and the confirmation email goes out exactly as it would for a booking made in the user interface.

Give the assistant a way to look up IDs

The action takes record IDs, not names, so on its own it cannot turn "Meeting Room 1" into a Resource. Put one of these on the server alongside it:

  • A read-only SOQL query tool, which lets the assistant resolve names to IDs itself. It reads any record the connected user can already read.

  • An autolaunched Flow of your own that returns the Resources and Reservation Types people book most, which keeps the assistant inside a list you control.

The records the assistant usually needs are B25__Resource__c for the room, desk, or table, and B25__Reservation_Type__c for the kind of booking.

Add the tool

  1. In Setup, open API Catalog > MCP Servers and select your server.

  2. Click Deactivate if the server is active.

  3. Click Add Server Assets, then Add Tools.

  4. Select the list view that holds Apex actions, then find GMCopilot__AgentforceReservationCreator.

  5. Click Add Tool next to it, then click Save.

  6. Open the Tools tab and enter the description below for the new tool.

  7. Leave Read-only and Idempotent cleared for this tool, then click Save.

  8. Click Activate.

The assistant now lists the reservation tool alongside the other two.

What the tool expects

The action takes a single input, serializedRequest. It is a JSON string rather than a JSON object, keyed by B25__Reservation__c field API names. B25__Start__c and B25__End__c are required, and in practice you also want B25__Resource__c and B25__Reservation_Type__c, since a Reservation without a Resource books nothing.

JSON
{
    "B25__Start__c": "2026-08-31T12:00:00.000Z",
    "B25__End__c": "2026-08-31T13:00:00.000Z",
    "B25__Resource__c": "a0Z...",
    "B25__Reservation_Type__c": "a0a..."
}

A successful call returns no data, so an empty result means the booking was created, not that nothing happened. A rejected booking returns the error GoMeddo raised, for example a conflict rule message, which the assistant can pass back to the person asking.

B25__Start__c and B25__End__c are UTC instants, while the availability tools report times in the org timezone. Convert before booking: 14:00 in Europe/Amsterdam on 2026-08-31 is 2026-08-31T12:00:00.000Z. Copying a time straight out of an availability result books the wrong hour.

Tool description

Replace the timezone in the example with your own org timezone, and keep the rest. Every sentence in it exists because a client got something wrong without it.

Creates a GoMeddo Reservation and sends the confirmation email. Not idempotent: two calls create two reservations. TIMEZONE: B25__Start__c and B25__End__c are UTC instants, but this org runs in Europe/Amsterdam, so 14:00 local on 2026-08-31 is 2026-08-31T12:00:00.000Z. Availability results are in local time, so never copy them here unchanged. INPUT: serializedRequest is a JSON STRING (not an object) keyed by B25__Reservation__c field API names. Required: B25__Start__c and B25__End__c; normally also B25__Resource__c and B25__Reservation_Type__c. Example: {"B25__Start__c":"2026-08-31T12:00:00.000Z","B25__End__c":"2026-08-31T13:00:00.000Z","B25__Resource__c":"a0Z..."}. Look up IDs with the query tool. Failures return an error; success returns no data.

Date and time formats

The Actions REST API behind the tools is strict about date and time values, and rejects a wrong format with UNKNOWN_EXCEPTION: Invalid Time, which does not say what was wrong. Use these formats.

Flow input type

Required format

Example

Date

YYYY-MM-DD

2026-08-28

Time

HH:mm:ss.SSSZ

10:00:00.000Z

Date/Time

YYYY-MM-DDTHH:mm:ss.SSSZ

2026-08-28T09:00:00.000Z

For time values the milliseconds and the trailing Z are both mandatory. The values 10:00, 10:00:00, 10:00:00.000, and 10:00:00Z are all rejected. This is why every tool description should end with its expected formats.

Verify the configuration

Ask the assistant a question you would normally answer by opening the calendar, for example how busy a specific building was last month, and check the number against the GoMeddo occupancy view for the same period.

A few things to look for on a first run:

  • The assistant lists the tools it can use, and the list matches what you activated.

  • Asking for a realistic one to three hour window returns resources. A request that spans a whole day often returns nothing, because a resource is only offered if it is free for the entire window, and most orgs have hours when nothing is bookable.

  • The answer matches what the GoMeddo calendar shows for the same question. If it does not, the Flow is the place to look, not the assistant.

  • A booking made through the reservation tool appears in the calendar at the time the person asked for, rather than an hour or two out.

Limitations

  • The server configuration cannot be shipped inside a managed package, so it is set up once per org rather than arriving preconfigured. Salesforce has said that partner packaged MCP servers are coming.

  • Only active autolaunched Flows and Apex invocable actions can back a tool. Flows of type PromptFlow cannot.

  • Tool descriptions are capped at 1024 characters.

  • An active server cannot be changed. Deactivate it first, or the change fails with Server must be inactive before making changes.

  • The External Client App has to be created by hand in Setup. It cannot be created programmatically.

  • Reservation creation takes record IDs rather than names, so it needs a lookup tool on the server beside it.

  • Conversation suits questions with a short answer and one-off bookings. Managing a term's timetable is still a job for the GoMeddo calendar.

Troubleshooting

Symptom

Cause

Resolution

401 Invalid token, even though signing in succeeded

The access token is not a JSON Web Token, so the gateway cannot validate it.

Enable Issue JSON Web Token (JWT)-based access tokens for named users on the External Client App, then reconnect the client.

invalid_client shortly after creating the app

The External Client App has not finished propagating.

Wait up to 30 minutes, then try again.

404 Server definition not found

The server exists but was never activated.

Open the server in Setup and click Activate.

UNKNOWN_EXCEPTION: Invalid Time

A time value is missing its milliseconds or its trailing Z.

Use HH:mm:ss.SSSZ, for example 10:00:00.000Z, and state the format in the tool description.

No results on a day that is clearly free

The requested window spans hours when nothing is bookable, and a resource is only returned if it is free for the whole window.

Ask again for a one to three hour window.

Server must be inactive before making changes

You are editing an active server.

Click Deactivate, make the change, then activate it again.

The assistant keeps picking the wrong tool

Two tools take the same inputs, or their descriptions do not say when each applies.

Expose one tool per distinct question and rewrite the descriptions to distinguish them.

A reservation is created one or two hours out

A local time was sent as if it were UTC.

Convert to UTC before booking, and name the org timezone in the reservation tool description.

The reservation tool returns nothing at all

The action returns no data on success.

An empty result means the booking was created. Open the Reservation in the GoMeddo calendar to confirm. A rejected booking returns an error message instead.