Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/agent-toolkit/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@mondaydotcomorg/agent-toolkit",
"version": "5.3.3",
"version": "5.4.0",


"description": "monday.com agent toolkit",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { ToolOutputType, ToolType } from '../../../tool';
import { BaseMondayApiTool, createMondayApiAnnotations } from '../base-monday-api-tool';
import { getAccountContextQuery } from './get-account-context.graphql';
import { GetAccountContextQuery } from '../../../../monday-graphql/generated/graphql/graphql';

export class GetAccountContextTool extends BaseMondayApiTool<undefined> {
name = 'get_account_context';
type = ToolType.READ;
annotations = createMondayApiAnnotations({
title: 'Get Account Context',
readOnlyHint: true,
destructiveHint: false,
idempotentHint: true,
});

getDescription(): string {
return (
"Fetch the current user's account information including account identity, plan details, active products, and configuration. " +
'Use this tool when you need to: ' +
'identify which account the user belongs to (id, name, slug), ' +
"check the account's plan tier, billing period, or user limits (max_users), " +
'count how many people/members are in the account (returns active_members_count — PREFERRED over listing users when only the count is needed), ' +
'discover which products are active (core, CRM, software, service, marketing, forms, whiteboard), ' +
'determine trial status (is_during_trial, is_trial_expired), ' +
'or get account-level settings (first_day_of_the_week, show_timeline_weekends, country_code).'
);
}

getInputSchema(): undefined {
return undefined;
}

protected async executeInternal(): Promise<ToolOutputType<never>> {
const { me } = await this.mondayApi.request<GetAccountContextQuery>(getAccountContextQuery, {});

if (!me) {
return {
content: 'AUTHENTICATION_ERROR: Unable to fetch account context. Verify API token and user permissions.',
};
}

return {
content: me.account,
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { gql } from 'graphql-request';

export const getAccountContextQuery = gql`
query GetAccountContext {
me {
account {
id
name
slug
tier
country_code
created_at
first_day_of_the_week
active_members_count
is_during_trial
is_trial_expired
show_timeline_weekends
sign_up_product_kind
plan {
tier
period
max_users
version
}
products {
id
kind
tier
default_workspace_id
}
}
}
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { MondayAgentToolkit } from 'src/mcp/toolkit';
import { callToolByNameRawAsync, createMockApiClient, parseToolResult } from '../test-utils/mock-api-client';
import { GetAccountContextQuery } from 'src/monday-graphql/generated/graphql/graphql';
import { FirstDayOfTheWeek } from 'src/monday-graphql/generated/graphql/graphql';

describe('GetAccountContextTool', () => {
let mocks: ReturnType<typeof createMockApiClient>;

beforeEach(() => {
mocks = createMockApiClient();
jest.spyOn(MondayAgentToolkit.prototype as any, 'createApiClient').mockReturnValue(mocks.mockApiClient);
});

const fullAccountResponse: GetAccountContextQuery = {
me: {
account: {
id: '12345',
name: 'Acme Corp',
slug: 'acme-corp',
tier: 'enterprise',
country_code: 'US',
created_at: '2023-01-15',
first_day_of_the_week: FirstDayOfTheWeek.Monday,
active_members_count: 150,
is_during_trial: false,
is_trial_expired: false,
show_timeline_weekends: false,
sign_up_product_kind: 'core',
plan: {
tier: 'enterprise',
period: 'yearly',
max_users: 500,
version: 3,
},
products: [
{ id: '1', kind: 'core', tier: 'enterprise', default_workspace_id: '100' },
{ id: '2', kind: 'crm', tier: 'enterprise', default_workspace_id: '200' },
null,
],
},
},
};

it('should fetch full account context with plan and products', async () => {
mocks.setResponse(fullAccountResponse);

const result = await callToolByNameRawAsync('get_account_context', {});
const parsed = parseToolResult(result);

expect(parsed.id).toBe('12345');
expect(parsed.name).toBe('Acme Corp');
expect(parsed.slug).toBe('acme-corp');
expect(parsed.tier).toBe('enterprise');
expect(parsed.plan.tier).toBe('enterprise');
expect(parsed.plan.period).toBe('yearly');
expect(parsed.plan.max_users).toBe(500);
expect(parsed.products).toEqual([
{ id: '1', kind: 'core', tier: 'enterprise', default_workspace_id: '100' },
{ id: '2', kind: 'crm', tier: 'enterprise', default_workspace_id: '200' },
null,
]);
});

it('should handle account with minimal/null optional fields', async () => {
const minimalResponse: GetAccountContextQuery = {
me: {
account: {
id: '99999',
name: 'Minimal Co',
slug: 'minimal-co',
tier: null,
country_code: null,
created_at: null,
first_day_of_the_week: FirstDayOfTheWeek.Sunday,
active_members_count: null,
is_during_trial: null,
is_trial_expired: null,
show_timeline_weekends: true,
sign_up_product_kind: null,
plan: null,
products: null,
},
},
};

mocks.setResponse(minimalResponse);

const result = await callToolByNameRawAsync('get_account_context', {});
const parsed = parseToolResult(result);

expect(parsed.id).toBe('99999');
expect(parsed.name).toBe('Minimal Co');
expect(parsed.plan).toBeNull();
expect(parsed.products).toBeNull();
});

it('should return auth error when me is null', async () => {
mocks.setResponse({ me: null });

const result = await callToolByNameRawAsync('get_account_context', {});

expect(result.content[0].text).toBe(
'AUTHENTICATION_ERROR: Unable to fetch account context. Verify API token and user permissions.',
);
});

it('should handle GraphQL error', async () => {
mocks.setError('Unauthorized');
const result = await callToolByNameRawAsync('get_account_context', {});
expect(result.content[0].text).toBe('Failed to execute tool get_account_context: Unauthorized');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import { CreateUpdateInMondayTool } from './create-update-tool-ui/create-update-
import { UpdateAssetsOnItemTool } from './update-assets-on-item-tool/update-assets-on-item-tool';
import { GetAssetsTool } from './get-assets-tool/get-assets-tool';
import { UserContextTool } from './user-context-tool/user-context-tool';
import { GetAccountContextTool } from './get-account-context/get-account-context-tool';
import { GetNotetakerMeetingsTool } from './get-notetaker-meetings-tool/get-notetaker-meetings-tool';
import { UndoActionTool } from './undo-action-tool/undo-action-tool';

Expand Down Expand Up @@ -114,6 +115,7 @@ export const allGraphqlApiTools: BaseMondayApiToolConstructor[] = [
BoardInsightsTool,
SearchTool,
UserContextTool,
GetAccountContextTool,
UpdateAssetsOnItemTool,
GetAssetsTool,
GetNotetakerMeetingsTool,
Expand Down Expand Up @@ -193,6 +195,7 @@ export * from './move-object-tool/move-object-tool';
export * from './board-insights/board-insights-tool';
export * from './search-tool/search-tool';
export * from './user-context-tool/user-context-tool';
export * from './get-account-context/get-account-context-tool';
export * from './update-assets-on-item-tool/update-assets-on-item-tool';
export * from './get-assets-tool/get-assets-tool';
// Notetaker Tools
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type Documents = {
"\n mutation CreateWidget($parent: WidgetParentInput!, $kind: ExternalWidget!, $name: String!, $settings: JSON!) {\n create_widget(parent: $parent, kind: $kind, name: $name, settings: $settings) {\n id\n name\n kind\n parent {\n kind\n id\n }\n }\n }\n": typeof types.CreateWidgetDocument,
"\n query getBoardData($boardId: ID!, $itemsLimit: Int!, $queryParams: ItemsQuery) {\n boards(ids: [$boardId]) {\n id\n name\n items_page(limit: $itemsLimit, query_params: $queryParams) {\n items {\n id\n name\n column_values {\n id\n text\n type\n value\n ... on PeopleValue {\n persons_and_teams {\n id\n kind\n }\n }\n }\n updates {\n id\n creator_id\n text_body\n created_at\n replies {\n id\n text_body\n created_at\n creator_id\n }\n }\n }\n }\n columns {\n id\n title\n type\n settings\n }\n }\n }\n": typeof types.GetBoardDataDocument,
"\n query getUsersByIds($userIds: [ID!]!) {\n users(ids: $userIds) {\n id\n name\n photo_tiny\n }\n }\n": typeof types.GetUsersByIdsDocument,
"\n query GetAccountContext {\n me {\n account {\n id\n name\n slug\n tier\n country_code\n created_at\n first_day_of_the_week\n active_members_count\n is_during_trial\n is_trial_expired\n show_timeline_weekends\n sign_up_product_kind\n plan {\n tier\n period\n max_users\n version\n }\n products {\n id\n kind\n tier\n default_workspace_id\n }\n }\n }\n }\n": typeof types.GetAccountContextDocument,
"\n query getAssets($ids: [ID!]!) {\n assets(ids: $ids) {\n id\n name\n file_extension\n file_size\n public_url\n url\n url_thumbnail\n created_at\n original_geometry\n uploaded_by {\n id\n name\n }\n }\n }\n": typeof types.GetAssetsDocument,
"\n query GetBoardAllActivity(\n $boardId: ID!\n $fromDate: ISO8601DateTime!\n $toDate: ISO8601DateTime!\n $limit: Int = 1000\n $page: Int = 1\n $includeData: Boolean!\n ) {\n boards(ids: [$boardId]) {\n name\n url\n activity_logs(from: $fromDate, to: $toDate, limit: $limit, page: $page) {\n user_id\n entity\n event\n data @include(if: $includeData)\n created_at\n }\n }\n }\n": typeof types.GetBoardAllActivityDocument,
"\n query GetBoardInfo($boardId: ID!) {\n boards(ids: [$boardId]) {\n # Basic Board Metadata\n id\n name\n description\n state\n board_kind\n permissions\n url\n\n # Timestamps\n updated_at\n\n # Board Configuration\n item_terminology\n items_count\n items_limit\n\n # Creator Information\n creator {\n id\n name\n email\n }\n\n # Workspace Information\n workspace {\n id\n name\n kind\n description\n }\n\n board_folder_id\n\n # All Columns with Full Metadata\n columns {\n id\n title\n description\n type\n settings\n }\n\n # All Groups with Metadata\n groups {\n id\n title\n }\n\n # Board Owners (Individual Users)\n owners {\n id\n name\n }\n\n # Team Owners\n team_owners {\n id\n name\n picture_url\n }\n\n # Board Tags\n tags {\n id\n name\n }\n\n # Top Group (default group)\n top_group {\n id\n }\n\n # Board Views (filters, sorts, and display configurations)\n views {\n id\n name\n type\n settings\n filter\n sort\n }\n }\n }\n": typeof types.GetBoardInfoDocument,
Expand Down Expand Up @@ -152,6 +153,7 @@ const documents: Documents = {
"\n mutation CreateWidget($parent: WidgetParentInput!, $kind: ExternalWidget!, $name: String!, $settings: JSON!) {\n create_widget(parent: $parent, kind: $kind, name: $name, settings: $settings) {\n id\n name\n kind\n parent {\n kind\n id\n }\n }\n }\n": types.CreateWidgetDocument,
"\n query getBoardData($boardId: ID!, $itemsLimit: Int!, $queryParams: ItemsQuery) {\n boards(ids: [$boardId]) {\n id\n name\n items_page(limit: $itemsLimit, query_params: $queryParams) {\n items {\n id\n name\n column_values {\n id\n text\n type\n value\n ... on PeopleValue {\n persons_and_teams {\n id\n kind\n }\n }\n }\n updates {\n id\n creator_id\n text_body\n created_at\n replies {\n id\n text_body\n created_at\n creator_id\n }\n }\n }\n }\n columns {\n id\n title\n type\n settings\n }\n }\n }\n": types.GetBoardDataDocument,
"\n query getUsersByIds($userIds: [ID!]!) {\n users(ids: $userIds) {\n id\n name\n photo_tiny\n }\n }\n": types.GetUsersByIdsDocument,
"\n query GetAccountContext {\n me {\n account {\n id\n name\n slug\n tier\n country_code\n created_at\n first_day_of_the_week\n active_members_count\n is_during_trial\n is_trial_expired\n show_timeline_weekends\n sign_up_product_kind\n plan {\n tier\n period\n max_users\n version\n }\n products {\n id\n kind\n tier\n default_workspace_id\n }\n }\n }\n }\n": types.GetAccountContextDocument,
"\n query getAssets($ids: [ID!]!) {\n assets(ids: $ids) {\n id\n name\n file_extension\n file_size\n public_url\n url\n url_thumbnail\n created_at\n original_geometry\n uploaded_by {\n id\n name\n }\n }\n }\n": types.GetAssetsDocument,
"\n query GetBoardAllActivity(\n $boardId: ID!\n $fromDate: ISO8601DateTime!\n $toDate: ISO8601DateTime!\n $limit: Int = 1000\n $page: Int = 1\n $includeData: Boolean!\n ) {\n boards(ids: [$boardId]) {\n name\n url\n activity_logs(from: $fromDate, to: $toDate, limit: $limit, page: $page) {\n user_id\n entity\n event\n data @include(if: $includeData)\n created_at\n }\n }\n }\n": types.GetBoardAllActivityDocument,
"\n query GetBoardInfo($boardId: ID!) {\n boards(ids: [$boardId]) {\n # Basic Board Metadata\n id\n name\n description\n state\n board_kind\n permissions\n url\n\n # Timestamps\n updated_at\n\n # Board Configuration\n item_terminology\n items_count\n items_limit\n\n # Creator Information\n creator {\n id\n name\n email\n }\n\n # Workspace Information\n workspace {\n id\n name\n kind\n description\n }\n\n board_folder_id\n\n # All Columns with Full Metadata\n columns {\n id\n title\n description\n type\n settings\n }\n\n # All Groups with Metadata\n groups {\n id\n title\n }\n\n # Board Owners (Individual Users)\n owners {\n id\n name\n }\n\n # Team Owners\n team_owners {\n id\n name\n picture_url\n }\n\n # Board Tags\n tags {\n id\n name\n }\n\n # Top Group (default group)\n top_group {\n id\n }\n\n # Board Views (filters, sorts, and display configurations)\n views {\n id\n name\n type\n settings\n filter\n sort\n }\n }\n }\n": types.GetBoardInfoDocument,
Expand Down Expand Up @@ -350,6 +352,10 @@ export function graphql(source: "\n query getBoardData($boardId: ID!, $itemsLim
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n query getUsersByIds($userIds: [ID!]!) {\n users(ids: $userIds) {\n id\n name\n photo_tiny\n }\n }\n"): (typeof documents)["\n query getUsersByIds($userIds: [ID!]!) {\n users(ids: $userIds) {\n id\n name\n photo_tiny\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n query GetAccountContext {\n me {\n account {\n id\n name\n slug\n tier\n country_code\n created_at\n first_day_of_the_week\n active_members_count\n is_during_trial\n is_trial_expired\n show_timeline_weekends\n sign_up_product_kind\n plan {\n tier\n period\n max_users\n version\n }\n products {\n id\n kind\n tier\n default_workspace_id\n }\n }\n }\n }\n"): (typeof documents)["\n query GetAccountContext {\n me {\n account {\n id\n name\n slug\n tier\n country_code\n created_at\n first_day_of_the_week\n active_members_count\n is_during_trial\n is_trial_expired\n show_timeline_weekends\n sign_up_product_kind\n plan {\n tier\n period\n max_users\n version\n }\n products {\n id\n kind\n tier\n default_workspace_id\n }\n }\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
Expand Down
Loading
Loading