Skip to main content
Glama

get_user_invite

Read-onlyIdempotent

Retrieve an invitation by ID to view its email, role, status, and expiry. Use for pending invites only.

Instructions

Get one invitation by invite id and return its email, role, status, and expiry. Use this for pending invites only; use get_user for accepted users.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
invite_idYesThe invite ID to retrieve

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
okYesWhether the tool call succeeded and returned structured data
dataNoStructured success payload when ok is true
errorNoStructured error payload when ok is false

Implementation Reference

  • MCP tool handler for 'get_user_invite'. Registers the tool with name 'get_user_invite', description about retrieving an invitation by ID, schema from USERS_TOOL_SCHEMAS.getUserInvite, and calls service.users.getUserInvite(params.invite_id). Returns a formatted user invite as JSON text content.
    // Phase 1: Get user invite tool
    server.tool(
    	"get_user_invite",
    	"Get one invitation by invite id and return its email, role, status, and expiry. Use this for pending invites only; use get_user for accepted users.",
    	USERS_TOOL_SCHEMAS.getUserInvite,
    	async (params) => {
    		const invite = await service.users.getUserInvite(params.invite_id);
    		return {
    			content: [
    				{
    					type: "text",
    					text: JSON.stringify(formatUserInvite(invite), null, 2),
    				},
    			],
    		};
    	},
  • Zod schema for the get_user_invite tool's input parameter. Defines 'invite_id' as a required string describing 'The invite ID to retrieve'.
    getUserInvite: {
    	invite_id: z.string().describe("The invite ID to retrieve"),
    },
  • The registerUsersTools function registers all user-related MCP tools including get_user_invite on the McpServer instance.
    export function registerUsersTools(
    	server: McpServer,
    	service: PortkeyService,
    ): void {
    	// List all users tool
    	server.tool(
    		"list_all_users",
    		"List accepted org users with id, name, email, role, and timestamps. Use this to find a user_id before get_user, update_user, delete_user, or add_workspace_member; use list_user_invites for pending invitations.",
    		USERS_TOOL_SCHEMAS.listAllUsers,
    		async () => {
    			const users = await service.users.listUsers();
    			return {
    				content: [
    					{
    						type: "text",
    						text: JSON.stringify(
    							{
    								total: users.total,
    								users: users.data.map(formatUser),
    							},
    							null,
    							2,
    						),
    					},
    				],
    			};
    		},
    	);
    
    	// Invite user tool
    	server.tool(
    		"invite_user",
    		"Invite a new org user and optionally provision workspace access and an API key in one call. Workspace assignments apply only after acceptance; use add_workspace_member or update_workspace_member later for follow-up changes.",
    		USERS_TOOL_SCHEMAS.inviteUser,
    		async (params) => {
    			const result = await service.users.inviteUser(params);
    			return {
    				content: [
    					{
    						type: "text",
    						text: JSON.stringify(
    							{
    								message: `Successfully invited ${params.email} as ${params.role}`,
    								invite_id: result.id,
    								invite_link: result.invite_link,
    							},
    							null,
    							2,
    						),
    					},
    				],
    			};
    		},
    	);
    
    	// User analytics tool
    	server.tool(
    		"get_user_stats",
    		"Return per-user request and cost analytics for a required time range. This is usage-by-user, not population metrics; use get_users_analytics for active-user or cohort trends.",
    		USERS_TOOL_SCHEMAS.getUserStats,
    		async (params) => {
    			const stats = await service.users.getUserGroupedData(params);
    			return {
    				content: [
    					{
    						type: "text",
    						text: JSON.stringify(
    							{
    								total_users: stats.total,
    								users: stats.data.map(formatUserAnalyticsGroup),
    							},
    							null,
    							2,
    						),
    					},
    				],
    			};
    		},
    	);
    
    	// Phase 1: Get user tool
    	server.tool(
    		"get_user",
    		"Get one accepted user by id and return their profile, role, and timestamps. Use list_all_users to find the id if you only have a name or email, and get_user_invite for pending invitations.",
    		USERS_TOOL_SCHEMAS.getUser,
    		async (params) => {
    			const user = await service.users.getUser(params.user_id);
    			return {
    				content: [
    					{
    						type: "text",
    						text: JSON.stringify(formatUser(user), null, 2),
    					},
    				],
    			};
    		},
    	);
    
    	// Phase 1: Update user tool
    	server.tool(
    		"update_user",
    		"Update a user's first name, last name, or organization role by id. Email and workspace roles are not editable here; use update_workspace_member for workspace membership changes.",
    		USERS_TOOL_SCHEMAS.updateUser,
    		async (params) => {
    			const { user_id, ...updateData } = params;
    			const user = await service.users.updateUser(user_id, updateData);
    			return {
    				content: [
    					{
    						type: "text",
    						text: JSON.stringify(
    							{
    								message: "Successfully updated user",
    								user: formatUser(user),
    							},
    							null,
    							2,
    						),
    					},
    				],
    			};
    		},
    	);
    
    	// Phase 1: Delete user tool
    	server.tool(
    		"delete_user",
    		"Delete a user from the org by id. This is permanent, removes org and workspace memberships, revokes API keys, and ends active sessions; use delete_user_invite for pending invites instead.",
    		USERS_TOOL_SCHEMAS.deleteUser,
    		async (params) => {
    			await service.users.deleteUser(params.user_id);
    			return {
    				content: [
    					{
    						type: "text",
    						text: JSON.stringify(
    							{
    								message: `Successfully deleted user ${params.user_id}`,
    								success: true,
    							},
    							null,
    							2,
    						),
    					},
    				],
    			};
    		},
    	);
    
    	// Phase 1: List user invites tool
    	server.tool(
    		"list_user_invites",
    		"List pending and sent invitations with id, email, role, status, and expiry. Use this to check invite state; use list_all_users for users who already accepted.",
    		USERS_TOOL_SCHEMAS.listUserInvites,
    		async () => {
    			const invites = await service.users.listUserInvites();
    			return {
    				content: [
    					{
    						type: "text",
    						text: JSON.stringify(
    							{
    								total: invites.total,
    								invites: invites.data.map(formatUserInvite),
    							},
    							null,
    							2,
    						),
    					},
    				],
    			};
    		},
    	);
    
    	// Phase 1: Get user invite tool
    	server.tool(
    		"get_user_invite",
    		"Get one invitation by invite id and return its email, role, status, and expiry. Use this for pending invites only; use get_user for accepted users.",
    		USERS_TOOL_SCHEMAS.getUserInvite,
    		async (params) => {
    			const invite = await service.users.getUserInvite(params.invite_id);
    			return {
    				content: [
    					{
    						type: "text",
    						text: JSON.stringify(formatUserInvite(invite), null, 2),
    					},
    				],
    			};
    		},
    	);
    
    	// Phase 1: Delete user invite tool
    	server.tool(
    		"delete_user_invite",
    		"Delete a pending invite and revoke its invite link. This does not affect existing users; use delete_user for full user removal.",
    		USERS_TOOL_SCHEMAS.deleteUserInvite,
    		async (params) => {
    			await service.users.deleteUserInvite(params.invite_id);
    			return {
    				content: [
    					{
    						type: "text",
    						text: JSON.stringify(
    							{
    								message: `Successfully deleted invite ${params.invite_id}`,
    								success: true,
    							},
    							null,
    							2,
    						),
    					},
    				],
    			};
    		},
    	);
    
    	// Phase 1: Resend user invite tool
    	server.tool(
    		"resend_user_invite",
    		"Resend the email for a pending invite that has not been accepted, unlike invite_user which creates a new invite. This sends a fresh email without modifying the invite record, expiry, or role; use get_user_invite first if you are unsure whether the invite still exists and list_user_invites to discover invite_ids.",
    		USERS_TOOL_SCHEMAS.resendUserInvite,
    		async (params) => {
    			await service.users.resendUserInvite(params.invite_id);
    			return {
    				content: [
    					{
    						type: "text",
    						text: JSON.stringify(
    							{
    								message: `Successfully resent invite ${params.invite_id}`,
    								success: true,
    							},
    							null,
    							2,
    						),
    					},
    				],
    			};
    		},
    	);
    }
  • Helper function formatUserInvite that transforms a UserInvite object into a simplified response format with id, email, role, status, created_at, and expires_at fields.
    function formatUserInvite(invite: UserInvite): {
    	id: string;
    	email: string;
    	role: string;
    	status: string;
    	created_at: string;
    	expires_at: string;
    } {
    	return {
    		id: invite.id,
    		email: invite.email,
    		role: invite.role,
    		status: invite.status,
    		created_at: invite.created_at,
    		expires_at: invite.expires_at,
    	};
    }
  • Service method getUserInvite that makes a GET request to /admin/users/invites/{inviteId} and returns a UserInvite object. This is the actual data-access layer that calls the backend API.
    async getUserInvite(inviteId: string): Promise<UserInvite> {
    	return this.get<UserInvite>(
    		`/admin/users/invites/${this.encodePathSegment(inviteId)}`,
    	);
    }
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false, idempotentHint=true. The description adds that it returns specific fields (email, role, status, expiry) and that it's for pending invites. There is no contradiction, and the behavior is well disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, no unnecessary words. It front-loads the purpose and includes usage guidance in a compact form.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a single parameter, strong annotations, and the presence of an output schema (context shows has output schema: true), the description is sufficient. It covers what the tool does, what it returns, and when to use it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The only parameter is invite_id, which has a clear schema description ('The invite ID to retrieve'). The tool description does not add further semantic detail beyond what the schema already provides. With 100% schema coverage, the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool retrieves a single invitation by ID and lists the returned fields (email, role, status, expiry). It also distinguishes from get_user by explicitly stating 'Use this for pending invites only; use get_user for accepted users.'

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance: 'Use this for pending invites only; use get_user for accepted users.' This tells the agent when to use this tool vs. an alternative sibling.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

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/s-b-e-n-s-o-n/portkey-admin-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server