
NOTICE: All information contained herein is, and remains
the property of TechnoCore.
The intellectual and technical concepts contained
herein are proprietary to TechnoCore and dissemination of this information or reproduction of this material
is strictly forbidden unless prior written permission is obtained
from TechnoCore.
The ObjAiMcpGoogle class provides an interface to Google's Gemini family of language models. It is part of the Multi-Cloud Provider (MCP) framework and inherits from the ObjAiMcpBase class.
The class is initialized with the following parameters:
def __init__(self, db=0, api_key: str = "", model: str = "gemini-pro"):
db: The database connection object.api_key: Your Google AI API key.model: The specific Gemini model to use (e.g., "gemini-pro", "gemini-pro-vision").promptSends a prompt to the specified Gemini model and returns the response.
def prompt(self, role: str = "", prompt: str = "", image_base64: str = "") -> str:
role: The system role for the AI (e.g., "You are a helpful assistant.").prompt: The user's prompt or question.image_base64: A base64-encoded image for multimodal prompts.To use the Google provider, you must first configure your API key in the config.yaml file under the ai_mcp_google section.
ai_mcp_google:
api_key: YOUR_GOOGLE_API_KEY
You can then instantiate and use the ObjAI class with the appropriate model string:
ai_obj = ObjAI(db=0, model="mcp:google:gemini-pro")
response = ai_obj.prompt("You are a helpful assistant.", "Who wrote the play Romeo and Juliet?")
print(response)
__init__ takes an api_key; when none is passed it calls
resolve_api_key(), which reads config through get_ini_value and
therefore resolves per active package. That is what makes a
per-package AI policy work: a package overriding ai_mcp_google or
gemini in its own section gets its own credential.
| Where | Shape | State on 2026-08-19 |
|---|---|---|
ai_mcp_google.api_key |
bare string, as every other MCP client | 19-char placeholder, rejected by the API |
gemini.keys |
list of {description, token} |
two working keys and one placeholder |
gemini.token |
bare string | does not exist; read by the deleted CLI wrapper |
gemini.api_key |
bare string | does not exist; read by ObjServiceNotification |
Four names for one credential, and only the list held anything that
worked. resolve_api_key() reads the first two and skips values that
cannot be keys, so a placeholder cannot shadow a real key later in the
list — which is exactly the arrangement in config: the dud sits
between two working entries.
Both helpers now live in ObjAiMcpBase (resolve_google_api_key,
google_key_looks_real) rather than on this class, because
ObjServiceNotification needs the same resolution and importing this
module would drag in the google.generativeai SDK and PIL for the
sake of a string. This class delegates.
looks_like_a_key() is a placeholder filter, not validation. A
Google key is 39 characters starting AIza; the check rejects anything
under 30 or ending _KEY. Only the API can say whether a key works, and
that answer arrives at call time.
gemini-pro no longer existsIt was this class's default model. The models endpoint does not list it,
so every call failed on the model name before the key was even in
question. DEFAULT_MODEL is now gemini-2.5-flash — current, and the
fastest of the family (0.8s for a trivial prompt on -lite, 1.9s on
-flash, measured 2026-08-19).
factory.ai/package.llm/ObjAIGemini.py shelled out to a gemini binary
that is not installed — and caught only CalledProcessError, so the
FileNotFoundError that actually occurs escaped uncaught. It read the
non-existent gemini.token, and its typer entry point did
P = ObjPrompt (the class) then P.query_gemini("", ""), binding
self="" and dropping the prompt it was given.
Nothing imported it, so it was deleted rather than kept as a shim, per
the deprecation rule in the standards. This client is the only Gemini
path.
google.genai (2026-08-19)google.generativeai is end-of-life — it announces on import that it
receives no further updates or bug fixes — and it never exposed
thinking-token counts, so spend on a reasoning model was invisible.
old google.generativeai |
new google.genai |
|
|---|---|---|
| client | genai.configure() + GenerativeModel(model) |
genai.Client(api_key=…) |
| call | client.generate_content(contents) |
client.models.generate_content(model=, contents=, config=) |
| image | PIL Image.open(io.BytesIO(...)) |
types.Part.from_bytes(data=, mime_type=) |
| thinking tokens | not exposed | usage_metadata.thoughts_token_count |
The model is now passed per call, not bound to the client.
record_usage gained reasoning_tokens because they are billed and are
in neither the prompt nor the candidate count. Measured on
gemini-2.5-flash, one sentence in and out: prompt 16, output 34,
thinking 919, total 969. Anything costing prompt+completion
understates by roughly twenty times.
thinking_budget — configurable, and off by defaultai_mcp_google.thinking_budget (per package). Left unset the model
decides, deliberately: a reasoning model answers differently with
thinking disabled, so it is not switched off behind the caller's back.
0 disables, -1 is dynamic, a number caps it.
The LITE models reject the config outright — 400 INVALID_ARGUMENT —
so a budget set for the flash models would break every lite call.
prompt() retries once without the config on that specific error rather
than keeping a list of which model accepts what.
Model retirement has broken this class twice: gemini-pro is gone, and
gemini-2.5-flash-lite is still listed by the models endpoint while
answering 404 "no longer available to new users" on call — so the
listing is no guide to what is callable. That argues for the
gemini-flash-latest alias.
Measurement killed the idea. The alias ignores thinking_budget — 76
and 97 thinking tokens across runs with it set to 0, where the pinned
models return exactly 0 — and runs 6.4–10.1s against 0.8–1.8s. So
DEFAULT_MODEL is gemini-3.5-flash; when it retires the failure is a
loud 404 rather than a silent 6× slowdown. A package pins its own with
ai_mcp_google.model.
gemini-2.5-pro and gemini-pro-latest answer 429 RESOURCE_EXHAUSTED
on this key — the free tier does not cover the pro models.