Little Green Light MCP Server
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| PORT | No | Port for Streamable HTTP mode (default: 3000). | |
| LGL_API_KEY | Yes | Your Little Green Light API key, generated in Settings > Integration > API Keys. | |
| LGL_MCP_TOKEN | No | Optional bearer token to secure the HTTP endpoint. | |
| LGL_READ_ONLY | No | Set to 'true' to enable read-only or assisted mode (combine with LGL_ASSISTED_MODE for assisted). | |
| LGL_ASSISTED_MODE | No | Set to 'true' with LGL_READ_ONLY='true' to enable assisted mode (notes and human-reviewed writes). | |
| LGL_INTEGRATION_LISTENER_URL | No | URL of the LGL Integration Queue webhook listener for human-reviewed writes. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| search_constituentsA | Search for constituents by name, email, phone, or other keyword |
| search_constituents_advancedA | Server-side constituent search combining custom attribute filters (including blank/not-blank checks) with standard LGL filters (keyword, location, membership, groups, lists, updated date) and an optional free-text query. All provided filters AND together, matching LGL's actual q[] behavior — there is no OR support. Custom attributes, keywords, groups, lists, and membership levels are all referenced by their display name (not internal LGL IDs); names are resolved and cached for the life of this server process, so only the first call referencing a given name pays a lookup round-trip. Filtering ON a custom attribute (via custom_attributes) works independently of whether its VALUE comes back in results — set include_custom_attrs to also fetch attribute values, which is otherwise omitted to keep responses small. |
| constituents_never_touched_attributeA | Find constituents that have NEVER had a given custom attribute touched — distinct from search_constituents_advanced's 'blank' operator, which only matches constituents that have a row for the attribute whose value happens to be empty. LGL's blank/not_blank operators both confirmed live to return zero matches for constituents that have no row for the attribute at all, so 'never touched' requires diffing the full constituent set against the union of blank+not_blank matches — there is no single LGL query for it. Paginates through both sets server-side (LGL's own filters compute the blank/not_blank sets; this only diffs the resulting ID sets, since LGL has no 'attribute row does not exist' query token). |
| list_constituentsC | List all constituents with optional pagination |
| get_constituentB | Get full details for a single constituent by ID. Writes an 'AI Access Log' note directly to that constituent's record noting when and by which tool it was accessed — this happens automatically in full and assisted (LGL_ASSISTED_MODE=true) modes, and is silently skipped under strict LGL_READ_ONLY. |
| create_constituentC | Create a new constituent in LGL |
| update_constituentB | Update an existing constituent's core information |
| delete_constituentB | Delete an existing constituent by ID |
| list_addressesA | List street addresses for a specific constituent |
| create_addressC | Add a street address to a constituent |
| update_addressB | Update an existing street address record by Address ID |
| delete_addressA | Delete a street address record by Address ID |
| list_phone_numbersC | List phone numbers for a specific constituent |
| create_phone_numberB | Add a phone number to a constituent |
| update_phone_numberC | Update an existing phone number record by Phone ID |
| delete_phone_numberA | Delete a phone number record by Phone ID |
| list_email_addressesB | List email addresses for a specific constituent |
| create_email_addressC | Add an email address to a constituent |
| update_email_addressA | Update an existing email address record by Email ID |
| delete_email_addressB | Delete an email address record by Email ID |
| list_web_addressesB | List web addresses (websites/social profiles) for a specific constituent |
| create_web_addressC | Add a web address to a constituent |
| update_web_addressC | Update an existing web address record by Web Address ID |
| delete_web_addressA | Delete a web address record by Web Address ID |
| list_giftsA | List gifts, either for a specific constituent (nested) or across the account (search). Supports date-range filtering via start_date/end_date (YYYY-MM-DD). |
| get_giftA | Get full details for a specific gift record by ID |
| record_giftB | Record a new gift nested under a specific constituent |
| update_giftA | Update an existing gift record by Gift ID |
| delete_giftB | Delete a specific gift record by Gift ID |
| list_campaignsB | List all campaigns |
| create_campaignC | Create a new fundraising campaign |
| get_campaignB | Get fundraising campaign details by ID |
| update_campaignC | Update an existing campaign details |
| delete_campaignB | Delete a campaign by ID |
| list_fundsB | List all funds |
| create_fundC | Create a new fund |
| get_fundA | Get fund details by ID |
| update_fundC | Update fund details |
| delete_fundB | Delete a fund by ID |
| list_eventsB | List all fundraising events |
| create_eventC | Create a new event |
| get_eventA | Get fundraising event details by ID |
| update_eventC | Update event details |
| delete_eventA | Delete an event by ID |
| list_appealsA | List all appeals |
| create_appealC | Create a new appeal |
| get_appealA | Get appeal details by ID |
| update_appealC | Update appeal details |
| delete_appealB | Delete an appeal by ID |
| list_appeal_requestsB | Fetch appeal requests, either for a specific appeal or for a specific constituent |
| create_appeal_requestC | Create a new appeal request, either linked to an appeal or constituent |
| get_appeal_requestA | Get details for an appeal request by ID |
| update_appeal_requestC | Update an appeal request details |
| delete_appeal_requestA | Delete an appeal request by ID |
| list_notesB | List notes, optionally filtered by constituent, or fetch all notes |
| get_noteA | Get full details of a note by ID |
| create_noteA | Log a new note nested under a specific constituent |
| update_noteB | Update an existing note record by Note ID |
| delete_noteA | Delete a note record by Note ID |
| log_document_linkA | NOT a real file attachment — LGL's API has no upload endpoint at all (even LGL's own web forms only accept a hosted URL, never raw file bytes). This logs a note on the constituent's record containing a link to a file hosted elsewhere (e.g. OneDrive, SharePoint, Google Drive) plus a short description, so the document is at least referenced and findable via list_notes/search_constituents. The linked file itself is not verified, downloaded, or stored by this server. |
| list_contact_reportsB | List contact reports, optionally filtered by constituent, or fetch all |
| search_contact_reportsC | Search across contact reports |
| get_contact_reportA | Get full details of a contact report by ID |
| create_contact_reportB | Create a new contact report nested under a constituent |
| update_contact_reportC | Update an existing contact report by ID |
| delete_contact_reportB | Delete a contact report by ID |
| list_volunteer_timesB | List volunteer times, optionally filtered by constituent, or fetch all |
| search_volunteer_timesC | Search for volunteer times |
| get_volunteer_timeA | Get volunteer time record details by ID |
| create_volunteer_timeB | Record volunteer hours nested under a constituent |
| update_volunteer_timeC | Update an existing volunteer hours record |
| delete_volunteer_timeB | Delete a volunteer time record by ID |
| list_relationshipsB | List constituent relationships for a specific constituent |
| create_relationshipB | Create a relationship between two constituents (nested under the parent constituent) |
| get_relationshipA | Get details for a constituent relationship by Relationship ID |
| update_relationshipA | Update relationship type between two constituents by Relationship ID |
| delete_relationshipA | Delete a constituent relationship by Relationship ID |
| list_class_affiliationsC | List class affiliations for a constituent |
| create_class_affiliationC | Add a class affiliation to a constituent |
| get_class_affiliationB | Get class affiliation details by ID |
| update_class_affiliationC | Update a class affiliation record |
| delete_class_affiliationA | Delete a class affiliation record by ID |
| list_class_affiliation_typesA | List all available class affiliation types |
| list_groupsA | List all constituent groups defined in LGL |
| create_groupC | Create a new constituent group |
| get_groupB | Get details for a single group by ID |
| update_groupB | Update constituent group details |
| delete_groupB | Delete a constituent group |
| list_group_membershipsC | List group memberships for a specific constituent |
| add_constituent_to_groupA | Add a constituent to a group (creates a group membership) |
| get_group_membershipB | Get details for a group membership record by ID |
| update_group_membershipC | Update a group membership record |
| remove_constituent_from_groupA | Remove a constituent from a group (deletes the group membership record by ID) |
| create_group_with_membersA | Creates a new LGL group and adds one or more constituents to it in a single call. This is the closest API-native substitute for LGL's UI-only saved/dynamic Lists — LGL's API has no endpoint to create or edit a List at all. Unlike a List, a group is a static set of members (not a live, re-run query); add or remove members afterward with add_constituent_to_group / remove_constituent_from_group. Partial failures (e.g. one bad constituent_id) don't fail the whole call — check each entry's result. |
| list_membershipsA | List membership program enrollments for a specific constituent |
| create_membershipC | Add a membership record to a constituent |
| get_membershipB | Get membership record details by ID |
| update_membershipC | Update a membership record by ID |
| delete_membershipA | Delete a membership record by ID |
| list_membership_levelsA | List all membership levels defined in LGL |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 148 tools
The overwhelming majority of tools use a clear entity+action pattern, so a CRUD tool for gifts, appeals, notes, etc. is easy to distinguish. The main friction points are the two invitation-creation tools (create_constituent_invitation vs create_event_invitation) and the cluster of constituent search/donor-lookup/report tools that overlap in audience even if their descriptions are careful.
Most tools consistently follow verb_noun snake_case (list_, get_, create_, update_, delete_, search_). Deviations such as record_gift, recent_donors/lapsed_donors/top_donors, add_constituent_to_group, and constituents_missing_info break the pattern but remain understandable.
At 148 tools this is an extreme surface for an MCP server, far beyond the 25+ threshold, and will create significant context overhead and selection difficulty. The broad entity coverage explains some of the size, but the toolset would be more usable split across focused servers or substantially consolidated.
The server covers full CRUD/lifecycle workflows for constituents, contact methods, gifts, campaigns, funds, events, appeals, notes, relationships, groups, memberships, volunteer time, class affiliations, and invitations, plus specialized donor analytics and review-queue submissions. The raw call_lgl_api passthrough also closes any remaining endpoint gaps, so there are no obvious dead ends.